Unity 物理系列七 布娃娃

參考
一文搞懂 Unity 布娃娃(Ragdoll)系統(tǒng) 讓角色更加真實(shí) (附實(shí)用Ragdoll插件詳解)
如何用Unity做出真實(shí)的布娃娃互動(dòng)效果?
Unity3D RagDoll(布娃娃系統(tǒng))詳解

一、布娃娃向?qū)?/h5>

官方文檔https://docs.unity.cn/cn/2019.4/Manual/wizard-RagdollWizard.html寫(xiě)的太簡(jiǎn)略了,可以參考B站的視頻如何使用Unity的布娃娃系統(tǒng)【Ragdoll】,這里我自己做了一遍,簡(jiǎn)單總結(jié)一下:

1.把模型拖到場(chǎng)景里,打開(kāi)布娃娃向?qū)?,進(jìn)行綁定,然后保存為預(yù)制體

我用了別的模型發(fā)現(xiàn)骨骼不太對(duì),還是從商店里下載視頻作者使用的免費(fèi)資源“BodyGuards”


image.png

導(dǎo)入后,把模型SkelMesh_Bodyguard_01拖入場(chǎng)景。然后從菜單欄中選擇 GameObject > 3D Object > Ragdoll… 以打開(kāi)布娃娃向?qū)?,按照部分綁定,記得最后改一下重量?/p>

image.png

現(xiàn)在選中模型,能看到添加的剛體輪廓。選 中節(jié)點(diǎn),能看到添加的組件:

image.png

角色關(guān)節(jié),可參考https://docs.unity.cn/cn/2019.4/Manual/class-CharacterJoint.html

2.需要打開(kāi)Physics Debugger協(xié)助微調(diào)
image.png
image.png

可以看到腿部紅色的碰撞體太粗了,手臂生成的碰撞體也不對(duì),要一點(diǎn)點(diǎn)調(diào)整。


image.png

這是調(diào)整后的結(jié)果,模型撞到下方的斜方塊后,會(huì)有布娃娃效果,不過(guò)手部僵硬,關(guān)節(jié)的彎曲角度也不正常。

3.給手添加碰撞
image.png

這里視頻UP主總是添加不上Connected Body,是因?yàn)橐付ǜ腹?jié)點(diǎn),而不是自身。

4.修改關(guān)節(jié)的彎曲角度

點(diǎn)這個(gè)edit按鈕進(jìn)入編輯

但是這里我設(shè)置的效果很不好,看了https://docs.unity.cn/cn/2019.4/Manual/class-CharacterJoint.html也沒(méi)搞明白那幾個(gè)軸。

5.Animator和布娃娃無(wú)法同時(shí)存在

默認(rèn)是播放動(dòng)畫(huà)狀態(tài):此時(shí)所有帶RigidBody節(jié)點(diǎn)的Is Kinematic勾選,Animator組件啟用。
當(dāng)需要啟動(dòng)布娃娃時(shí),使用代碼將所有帶RigidBody節(jié)點(diǎn)的Is Kinematic取消勾選,Animator組件禁用。

unity 布娃娃系統(tǒng)的開(kāi)啟關(guān)閉提供了代碼參考:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RangdollController : MonoBehaviour {

private Animator Anim;
// Use this for initialization
void Start () {
    Anim = GetComponent<Animator>();
    InitRagdoll();
}

// Update is called once per frame
void Update () {
    
}

public List<Rigidbody> RagdollRigidbodys = new List<Rigidbody>();
public List<Collider> RagdollColliders = new List<Collider>();
/// <summary>
/// 初始化,遍歷角色身體上的所有ragdoll并存儲(chǔ) 此時(shí)關(guān)閉布娃娃系統(tǒng)
/// </summary>
void InitRagdoll()
{
    Rigidbody[] Rigidbodys = GetComponentsInChildren<Rigidbody>();
    for (int i = 0; i < Rigidbodys.Length; i++)
    {
        if (Rigidbodys[i] == GetComponent<Rigidbody>())
        {
            //排除正常狀態(tài)的Rigidbody
            continue;
        }
        //添加Rigidbody和Collider到List
        RagdollRigidbodys.Add(Rigidbodys[i]);
        Rigidbodys[i].isKinematic = true;
        Collider RagdollCollider = Rigidbodys[i].gameObject.GetComponent<Collider>();
        RagdollCollider.isTrigger = true;
        RagdollColliders.Add(RagdollCollider);
    }
}
/// <summary>
/// 啟動(dòng)布娃娃系統(tǒng)
/// </summary>
public void EnableRagdoll()
{
    //開(kāi)啟布娃娃狀態(tài)的所有Rigidbody和Collider
    for (int i = 0; i < RagdollRigidbodys.Count; i++)
    {
        RagdollRigidbodys[i].isKinematic = false;
        RagdollColliders[i].isTrigger = false;
    }
    //關(guān)閉正常狀態(tài)的Collider
    GetComponent<Collider>().enabled = false;
    //下一幀關(guān)閉正常狀態(tài)的動(dòng)畫(huà)系統(tǒng)
    StartCoroutine(SetAnimatorEnable(false));
}
/// <summary>
/// 關(guān)閉布娃娃系統(tǒng)
/// </summary>
public void DisableRagdoll()
{
    //關(guān)閉布娃娃狀態(tài)的所有Rigidbody和Collider
    for (int i = 0; i < RagdollRigidbodys.Count; i++)
    {
        RagdollRigidbodys[i].isKinematic = true;
        RagdollColliders[i].isTrigger = true;
    }
    //開(kāi)啟正常狀態(tài)的Collider
    GetComponent<Collider>().enabled = true;
    //下一幀開(kāi)啟正常狀態(tài)的動(dòng)畫(huà)系統(tǒng)
    StartCoroutine(SetAnimatorEnable(true));
}
IEnumerator SetAnimatorEnable(bool Enable)
{
    yield return new WaitForEndOfFrame();
    Anim.enabled = Enable;
}
6.坑
  • 播放布娃娃的時(shí)候要把a(bǔ)nimator勾掉,不然不生效
  • 部位穿插拉伸,要把部位Character Joint組件上面的Enable Projection勾上
  • 激活布娃娃彈得很高,就是剛體的速度,把rigidbody的速度置為0
  • 如果布娃娃動(dòng)作僵硬,肯定用錯(cuò)骨骼來(lái)綁定布娃娃導(dǎo)致的
  • 布娃娃穿透場(chǎng)景碰撞的問(wèn)題,其實(shí)這個(gè)由于速度太快引起的,可以設(shè)置rigidbody的碰撞檢測(cè)模式collisionDetectionMode
  • 受力不要全部部位都給力,一般都是給一個(gè)部位就夠了,不然各種力作用引起怪異表現(xiàn)
  • 關(guān)于倒地之后抖動(dòng)問(wèn)題,這個(gè)只能加個(gè)檢測(cè),如果所有剛體速度小于某個(gè)數(shù)則關(guān)閉剛體功能
7.官方文檔 關(guān)節(jié)和布娃娃穩(wěn)定性

https://docs.unity.cn/cn/2019.4/Manual/RagdollStability.html

二、插件Ragdoll Mecanim Mixer
1.Ragdoll 原理

跟著布娃娃向?qū)ё鐾曛?,原理也就十分容易理解了。要想為人物添加Ragdoll效果,只需要在模型骨骼上掛載合適大小的碰撞體及剛體組件,讓骨骼運(yùn)動(dòng)受物理模擬驅(qū)動(dòng)(而非動(dòng)畫(huà)驅(qū)動(dòng)),即可實(shí)現(xiàn)基于物理效果的布娃娃系統(tǒng)。

Unity原生的布娃娃系統(tǒng)功能非常簡(jiǎn)單,我們可以點(diǎn)進(jìn)之前配置有碰撞體的骨骼節(jié)點(diǎn)觀察一下。 可以看到肢體骨骼只是增加了一個(gè)RigidBody和Collider用于物理模擬,同時(shí)用CharacterJoint連接肢體模擬關(guān)節(jié),剩余全部交給Unity物理系統(tǒng)進(jìn)行模擬。

2.原生 Ragdoll 系統(tǒng)不足

看過(guò)Unity Ragdoll系統(tǒng)后,很明顯能發(fā)現(xiàn)該套系統(tǒng)功能較為簡(jiǎn)單,有很大不足

  • 碰撞體、剛體等組件直接掛載在骨骼物體上,影響骨骼結(jié)構(gòu)的簡(jiǎn)單性,增加了耦合度
  • 沒(méi)有Animator組件,意味著該Ragdoll系統(tǒng)只能單純受物理驅(qū)動(dòng),無(wú)法與動(dòng)畫(huà)融合(因此Unity官方也建議僅將該系統(tǒng)用于角色死亡時(shí)表現(xiàn))
  • 狀態(tài)切換很困難、難以擴(kuò)展,且缺乏過(guò)渡(比如需要多套ragdoll不同表現(xiàn)時(shí),要修改碰撞體和剛體參數(shù)同時(shí)控制啟用)
3.插件Ragdoll Mecanim Mixer

Ragdoll Mecanim Mixer 插件正是為了解決上面的這些痛點(diǎn)而出現(xiàn)的,對(duì)于這些問(wèn)題,該插件都實(shí)現(xiàn)了很好的解決方案(該插件可在Asset Store購(gòu)買(mǎi),目前Unity最好的Ragdoll插件之一)

  • Ragdoll碰撞體與骨骼分離,不直接關(guān)聯(lián),降低耦合度
  • 基于分離結(jié)構(gòu),可以分別計(jì)算物理變換與動(dòng)畫(huà)變換,并實(shí)現(xiàn)融合
  • 基于一套R(shí)agdoll碰撞體可以預(yù)設(shè)多種狀態(tài),切換簡(jiǎn)單且可控制過(guò)渡平滑度

官方文檔:https://assetstore.altinqiran.kz/ramecan-mixer/files/GUIDE_ENG.pdf

該插件主要由兩個(gè)腳本組成

  • Ragdoll Constructor
  • Ramecan Mixer
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容