Unity Ragdoll 心得+坑点总结

Posted zhxmdefj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Ragdoll 心得+坑点总结相关的知识,希望对你有一定的参考价值。

Ragdoll有什么用

煮个栗子:守望先锋的玩家死亡时,会突然全身乏力,尸体的动作十分有趣

技术图片

技术图片

而Unity可以用ragdoll来实现这一效果

技术图片

技术图片

创建Ragdoll

在场景中新建 3D Object → Ragdoll...

技术图片

接下来是一个初见复杂的绑定界面,这里我做了简单翻译

技术图片

我们需要将模型对应的关节部位一一拉进这个表

创建完成后,可以发现模型中的每个所选部位中多了一个Rigibody,一个Collider和一个Character Joint组件,在Joint面板里可以调节转动限制等

技术图片

技术图片

这里要注意的一个坑点是,root节点是没有Character Joint的,当你找不到root节点时,没有Character Joint但是添加了Box Collider和Rigibody的就是root节点

技术图片

root节点应在这个位置,不熟悉朋友有可能将盆骨附近Pelvis 与 胸部附近Middle Spine的两个Collider互换位置,或者重叠,这将导致整个人物的抽搐,蒙皮拉伸

技术图片

调整四肢Collider大小位置,如下:

技术图片

通过代码控制

这时候我们要做:

  1. 让角色存活(isDead = false)时:每个部位的Rigibody的isKinematic一直为true,每个部位的Collider的isTrigger也为true
  2. 角色死亡(isDead = true)时:每个部位的Rigibody的isKinematic变为false,每个部位的Collider的isTrigger也变为false,同时,必须将角色的Animation组件去除

这时候就可以实现我我们想要的效果

技术图片

代码

我的做法是使用GetComponentsInChildren函数获得所有刚体,再通过每个刚体获取这个部位上的Collider,用两个List将他们存储起来。就可以方便的设置isKinematic和isTrigger

同时在死亡的下一帧用协程关闭动画组件,(如果想让角色复活,Anmiaton组件的enable属性设置为true即可)

技术图片

完整代码如下:

    public List<Rigidbody> ragdollRigidbodys = new List<Rigidbody>();
    public List<Collider> ragdollColliders = new List<Collider>();

    void InitRagdoll() {

        Rigidbody[] _rigidbodys = GetComponentsInChildren<Rigidbody>();

        for (int i = 0; i < _rigidbodys.Length; i++) {
            if (_rigidbodys[i] == rigidbody)
                continue;
            ragdollRigidbodys.Add(_rigidbodys[i]);
            _rigidbodys[i].isKinematic = true;

            Collider _collider = _rigidbodys[i].gameObject.GetComponent<Collider>();
            _collider.isTrigger = true;
            ragdollColliders.Add(_collider);

        }
    }

    void EnableRagdoll() {
        for (int i = 0; i < ragdollRigidbodys.Count; i++) {
            ragdollRigidbodys[i].isKinematic = false;
            ragdollColliders[i].isTrigger = false;
        }

        Collider collidercontroller = rigidbody.gameObject.GetComponent<Collider>();
        collidercontroller.enabled = false;
        rigidbody.isKinematic = true;

        StartCoroutine(CloseAnimator());
    }

    IEnumerator CloseAnimator() {
        yield return new WaitForEndOfFrame();
        animator.enabled = false;
        this.enabled = false;
    }

最终效果就是这样了,死亡之后的布娃娃状态真的很有意思

技术图片

技术图片

技术图片

坑点总结

第一帧蒙皮拉伸,撕裂

Play之后的第一帧(先点暂停再Play可查看第一帧)可能出现角色关节撕裂,Play之后角色乱动

技术图片

解决方案:

  • 检查pelvis和middle spine是否混淆,root节点设置错误(root节点是有刚体,有碰撞器没有Character Joint

  • 检查两个部位的collider是否产生重叠

死亡后蒙皮拉伸,撕裂

解决方案:

可以尝试勾选Character Joint组建的Enable Projection选项

技术图片

死亡后布娃娃不生效

解决方案

检查是否有关Animator组件

以上是关于Unity Ragdoll 心得+坑点总结的主要内容,如果未能解决你的问题,请参考以下文章

网易大咖分享之从Unity_RagDoll系统科普到动画全部基础原理

求Unity3D的人物模型!

UVa1589 Xiangqi 坑点总结+参考代码

Unity UGUI_DropDown控件模拟QQ分组的使用心得

Unity与安卓交互心得

(C#脚本)Unity中角色移动的几种实现方法,以及心得。(适合新手入门)