動態骨骼DynamicBone整理

關於布料模擬的方案早前就已經確定,DynamicBone作爲插件果哥在離職前已經實現下C++版本,正好最近由於部門架構調整可以安心回來做技術想對它進行下優化,於是耐心抽時間看了下目前的實現。在對比楚留香的效果時順帶問了大彌撒亞的實現,幾個項目也都基本採用彈簧質點模型用韋爾萊積分去迭代計算。只是測試下來目前實現性能存在問題,下面是簡要的整理與說明,希望在下週能把它優化到滿意程度

1. 簡介

DynamicBone是一個簡單的基於模擬彈簧振子的算法實現樹狀柔體的物理模擬插件。雖然基於模擬彈簧振子運動的算法實現,但是DynamicBone各節點之間的距離實際上不會發生變化, 比起彈簧,父子節點之間的相對運動更接近簡諧運動中的單擺。

2. 使用說明

DynamicBone的使用非常簡單,一句話說明,首先在Unity場景中選擇要應用DynamicBone組件的GameObject添加組件,然後確定自己要應用DynamicBone的子節點,把最上層的子節點 的GameObject設置爲DynamicBone組件的Root即可。然後設置各項參數,DynamicBone就會在物體發生運動的時候自動生效。要注意的問題有三個:

  • 因爲DynamicBone組件會在啓動時記錄所有節點的局部座標並且在每次Update時還原局部座標,同時會根據所在的GameObject的移動計算節點位置,所以添加DynamicBone組件的 GameObject不能位於應用DynamicBone的模型節點樹中,根節點也不行;
  • DynamicBone更新座標是在LateUpdate時進行的,這會導致DynamicBone的計算結果會覆蓋動畫輸出的位置;
  • DynamicBone所有節點變換更新時,如果某個子節點是父節點唯一的子節點,會把這一幀內子節點發生的相對旋轉同步到父節點上;

2.1. 關於碰撞

DynamicBone提供了簡單的碰撞算法,允許使用者禁止進入或者離開某些特定的區域,組件提供了球型和膠囊體兩種區域形狀。碰撞功能的使用非常簡單,只需要在希望與DynamicBone 節點發生碰撞交互的GameObject添加DynamicBoneCollider組件,並且設置以下屬性:

  • Center:指定區域中心與GameObject位置的偏移量;
  • Radius:區域內球形部分的半徑;
  • Height:區域高度,這個值在小於2倍Radius時無效,會使區域變成球型,高於2倍Radius時生效,區域會變成膠囊體(可視化模型是兩個球體);
  • Direction:膠囊體在當前GameObject局部座標的方向,區域是球體的時候無效;
  • Bound:區域模式,Outside表示區域會作爲碰撞盒與DynamicBone節點發生碰撞,阻止節點進入區域內,而Inside則會約束節點在區域內,阻止節點離開區域; 然後需要將DynamicBoneCollider對象添加至與其發生碰撞交互的DynamicBone組件的Colliders屬性中。

3. 重要屬性

DynamicBone有四個基本屬性,決定了其運動效果,四個屬性的取值範圍都是[0, 1]:

  1. Damping 阻尼:阻止簡諧運動的慣性運動,相當於彈簧的摩擦力。爲0時簡諧運動過程不會主動停止,爲1時簡諧運動過程不會發生;
  2. Elasticity 彈性:決定回振移動強度,在簡諧運動過程中作爲額外的作用力將節點拉到還原位置,相當於彈簧的彈力。爲0時系統形變不會主動還原,爲1時形變不會發生;
  3. Stiffness 剛性:限制最大振動幅度與方向,保證碰撞處理前節點不會跑到指定範圍外,相當於彈簧的硬度。爲0時不發揮作用,0到1時限制範圍從2倍原始距離到0線性衰減;
  4. Inert 慣性:限制形變幅度,在每一幀的簡諧運動迭代發生前,無條件隨物體整體運動拉動節點,拉動距離爲Inert * 整體運動距離;

4. 其他屬性說明

  1. Update 更新頻率:DynamicBone計算頻率,當遊戲實際幀率高於這個更新頻率時,DynamicBone會在每一幀進行消極計算,會盡量保持節點形狀,但不會進行簡諧運動模擬;當DynamicBone更新 頻率遠遠高於遊戲幀率的時候,DynamicBone會在腳本執行時嘗試追幀,但每次最多執行4次,也就是更新頻率實際最高只是當前遊戲幀數的4倍;
  2. Radius 半徑:指定每個節點與DynamicBoneCollider發生碰撞的半徑,注意節點互相之間不存在碰撞關係,注意這個半徑是0碰撞依然會生效;
  3. Damping\Elasticity\Stiffness\Inert\Radius各屬性的Distrib:指定屬性隨着節點深度遞增發生的變化;
  4. End Length\End Offset 末尾節點偏移量:指定特殊的末尾節點End Bone局部位置,詳見下方的4.1. 關於EndLength和EndOffset
  5. Gravity 重力:在DynamicBone節點上施加的重力,方向是在全局座標系中的,注意DynamicBone的重力比較特殊,只在節點運動發生時起效,會在節點運動時把節點向重力方向拉動;
  6. Force 常駐力:在DynamicBone節點上施加的額外力,方向是在全局座標系中的,注意Force與Gravity不同,是無條件生效的,會一直把節點向指定方向拉動;
  7. Colliders 碰撞體列表:會與DynamicBone各節點發生碰撞的碰撞體對象,詳見2.1. 關於碰撞
  8. Exclusions 排除節點列表:在設置Root節點後,DynamicBone會根據節點的GameObject的父子關係沿着子GameObject方向自動生成節點樹,Exclusions中所有節點及其子孫節點都不會 生成DynamicBone節點;
  9. Freeze Axis 固定軸:非None的情況下,所有節點在局部座標系的對應的軸上在值不會發生變化;
  10. DistanceDisable 距離控制開關:開啓或者關閉距離控制機制,開啓後如果DynamicBone所在的物體超出了參考物體的參考距離範圍,DynamicBone的所有行爲都會停止;
  11. Reference Object 參考物體:距離控制機制的參考物體,如果爲空則DynamicBone會選擇場景內的主攝影機作爲參考對象;
  12. Distance To Object 參考距離:距離控制機制的參考距離;

4.1. 關於EndLength和EndOffset

DynamicBone有一個虛擬的End Bone機制,通過設置EndLength和EndOffset開啓,當兩個屬性都是0時End Bone不會出現。DynamicBone每個骨骼節點與真實的GameObject是一一對應,但是 EndLength和EndOffset非0的時候,DynamicBone會創造一個虛擬的End Bone,作爲末尾節點的子節點。這個虛擬節點沒有對應的GameObject,所以其唯一的作用的就是將自己的相對旋轉更新到 自己的父節點,也就是原本的末尾節點(子節點旋轉同步到父節點的操作見2. 使用說明)。

EndLength和EndOffset的邏輯是,當EndLength爲0,DynamicBone會直接使用EndOffset,在EndOffset指示的局部偏移位置安排一個End Bone節點;如果EndLength不爲0,那麼EndOffset 會根據EndLength計算得到(設置的EndOffset值會被捨棄),計算方法是末尾節點的父節點沿末尾節點方向延伸EndLength長度,如果末尾節點就是根節點,則沿着末尾節點的局部座標的X軸延伸 EndLength。

5. 使用限制和缺陷

  1. 由於DynamicBone完全不發生拉伸和壓縮的特性,DynamicBone並不適合模擬凝膠、橡膠等各方向形變明顯的物體,而更適合模擬頭髮、繩子等不容易拉伸但容易形變的物體, 衣物則要看衣物材質是否容易拉伸,如果容易拉伸依然不適合用DynamicBone模擬;
  2. 雖然有簡單的碰撞機制,DynamicBone的各節點之間是不存在碰撞的(當然可以通過在各節點都設置DynamicBoneCollider組件來實現,但因爲開銷會很高所以不建議),這意味着DynamicBone 模擬的物體在剛性爲0的時候可能會發生自我穿插;
  3. DynamicBone的位置更新發生在LateUpdate節點,這意味着DynamicBone會完全控制節點的位置,其計算結果會覆蓋物理和動畫系統輸出的位置,而不能與其融合;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章