人類一敗塗地挺有意思的。

1. 前言

基於物理的動畫(Physically Based Animation)是計算機圖形學中的一個有趣的領域,它包括剛體模擬(Rigid Body Simulation)、柔體模擬(Soft Body Simulation)、流體模擬(Fluid Simulation)、粒子系統(Particle Systems)、蜂擁行為(Flocking)、基於物理的角色動畫(Physically Based Character Animation)等。

在動畫中添加物理,會使動畫更豐富,與場景交互也會更真實。本文介紹角色物理動畫最常見的實現之一——佈娃娃模擬,本文包括概念、驅動物理跟隨動畫的方式、UE5中的物理動畫代碼介紹等。

和之前的文章一樣,本文依然隻介紹骨骼,且為基礎篇,所以有些內容可以適當跳過~

應用篇請見下一篇文章~:

2. 一分鐘實現最簡單的角色物理動畫模擬

開頭先實現一個最簡單的物理動畫模擬,按照Physical Animation / Ragdoll TUTORIAL in Unreal Engine 4 latest version:https://www.youtube.com/watch?v=_Xnx9L6DgfE流程來。

打開角色藍圖,添加PhysicalAnimation組件,並設置Bone的值為pelvis,然後按下圖操作:

  • 選擇所有剛體,可以添加一個Physical Animation Profiles,然後選擇Assign,可以在Details面板中,看到PhysicalAnimation配置,這裡可以為每個剛體單獨配置數據。
  • 添加PhysicalAnimation組件,然後選擇Mesh,修改Collision,修改膠囊體的大小。
  • 然後編寫下面的邏輯,這裡創建瞭一個用於WorldSpace中的PhysicalAnimationData。

運行結果如下所示(效果與配置有關,不代表最終結果):

(這個表現…哈哈哈哈,emm…隻是為瞭引出後面的內容…

3. 佈娃娃物理系統(Ragdoll Physics System)

Ragdoll將物理和動畫結合起來,是一種由物理引擎驅動的程序式動畫(procedural Animation)。它是多個剛體(rigid)的集合(在骨骼動畫系統中,每個剛體通常與骨骼綁定在一起),通過限制骨骼的移動來實現。當角色死亡時,每個joint的運動都受到瞭限制,表現也會更真實。

4 前置概念及介紹

遊戲引擎所指的“角色物理”,更精確地說應稱為剛體動力學(rigid body dynamics)模擬。

關於物理資產編輯器的介紹,請見官方文檔:https://docs.unrealengine.com/5.0/en-US/physics-asset-editor-in-unreal-engine/

4.1 剛體(Rigid Bodies)

在理想狀態下,剛體在運動中和受力作用後,形狀和大小不變。

在UE5中,FBodyInstance繼承於FBodyInstanceCore,它描述瞭剛體,是物理數據描述的基本單位,包括:

  • TWeakObjectPtr< UBodySetupCore> BodySetup:共享的資源信息
  • CollisionEnabled:碰撞類型
  • LinearDamping、AngularDamping:線性阻尼、角速度阻尼
  • DOFConstraint:自由度約束
  • GetBodyMass():質量
  • GetBodyInertiaTensor():慣性張量,張量描述瞭圍繞任何給定軸旋轉物體的難度,慣性張量越高越穩定。
  • UpdatePhysicalMaterials():更新材質的摩擦、恢復系數等。

UBodySetup繼承於UBodySetupCore,它包含與單個資源關聯的碰撞信息,單個UBodySetup實例可以在多個FBodyInstance之間共享。它包括:

  • BoneName:骨骼名
  • PhysicsType:物理類型
    • Default:繼承父組件的設置
    • Kinematic:不受物理影響,但可以與物理模擬的物體交互
    • Simulated:使用物理模擬

USkeletalBodySetup繼承於UBodySetup,在父類的基礎上增加瞭一個bSkipScaleFromAnimation開放參數。

選擇物理資產編輯器中的body,可以在Details面板看到FBodyInstance含有的參數:

4.2 約束(Constraints)

無約束的剛體有6個自由度(degree of freedom, DOF):可以在3個維度上平移,並可以繞3個笛卡爾軸旋轉。

在物理引擎中,約束用於模擬物體間的連接情況,如連桿、佈娃娃、吊燈等。在一定程度上削減瞭DOF。

常見的約束類型:

  • point-to-point:點對點約束,剛體中某個指定的點與其他剛體的指定點對齊,比如球窩關節(ball and socket joint)。
  • hinge:鉸鏈約束,將連接物理的剛體的運動約束在某一個軸上,限制關節中的旋轉,比如膝蓋I(knees)、肘部(elbows)。有限制鉸鏈隻能在預設的角度內旋轉,無限制鉸鏈則允許物體旋轉無線圈。
  • ragdoll:身體上的約束,為模仿真實人體的關節運動而特別設計的,並使用約束鏈提高模擬的穩定性。
  • powered constraint:富動力約束,這個將在後文介紹。

骨骼關節的數量通常比佈娃娃剛體的數量多,剛體與骨骼之間存在著映射關系,UBodySetupCore中的BoneName即表示剛體與skeletal mesh中的bone相關聯。UE5中的剛體與骨骼之間的關系可以在物理資產中的Skeleton Tree中查看:

在UE5中,選擇Constraint,可以配置右邊的參數,對應的類是FConstraintInstance:

4.3 剛體狀態(Rigid Body States)

動畫表現可以分為三種類型:

  • 關鍵幀(KeyFramed):完全由動畫驅動。通常禁用剛體上的碰撞,與其他物體碰撞時動畫表現不能被修改。
  • 動力/動畫(Powered/Animated):由動畫驅動,但可以使用脈沖(impulses)或其他碰撞修改動畫表現。物理跟隨動畫。
  • 無動力/模擬(Unpowered/Simulated):不能由動畫驅動,隻受重力和約束影響。

神秘海域4的GDC演講(https://www.youtube.com/watch?v=7S-_vuoKgR4)中介紹瞭兩種控制器,分別用於Local Space和World Space控制,來實現物理跟隨動畫。兩種控制分別是:

  • 富動力約束控制器(Powered Constraint Controller),也稱為Motor。
    • 控制Local Space下的Rotation。Rotation Matching。
    • 難以匹配Animation Pose。
    • Havok物理引擎(他們使用的物理引擎)建議在死亡或垂死角色制作動畫時使用Motor,因為Motor在Local Space中工作(控制joint,可以產生非常逼真的結果)。
  • 剛體控制器(Rigid Body Controller),也稱為關鍵幀控制器(Keyframe Controller)。
    • 控制World Space下的Position。Position Matching。
    • 操縱單個剛體的速度以匹配動畫。線性的。
    • Havok物理引擎建議將此控制器用於實時角色,因為它在World Space中工作。
    • 代碼如下:(角速度也同樣)

currentLinearVelocity = getRigidBodyLinearVelocity(myRB)
currentLinearVelocity += Limit(poseLocalAcceleration, localAccelerationLimit) * localAccelerationGain
currentLinearVelocity += Limit(poseParentAcceleration, parentAccelerationLimit) * parentAccelerationGain
desiredVelocity = (currentRBPosition - desiredPosePosition) / deltaTime

currentLinearVelocity += (desiredVelocity - currentLinearVelocity) * positionGain
havokBody->setLinearVelocity(currentLinearVelocity