Unity Mesh角色换装与表情动画

发表于2018-11-19
评论2 9.7k浏览
Unity3D里面所有的模型都是由Mesh组成的。本篇文章主要是对Mesh的实例应用,看看Mesh是如何实现角色换装和表情动画的。

最终效果  

SkinnedMesh

对Mesh网格进行非刚体变化,即顶点变化,unity为我们封装成了SkinnedMesh。

这里是SkinnedMeshRenderer类的内容。

我们依次来理解下关键的几个的功能。

bones

bones属性是最重要的,美工出身的都对角色蒙皮了解,我们需要对角色进行骨骼蒙皮,调节权重,才能让角色流畅的动起来。bones属性相关骨骼的信息,他是以数组的形式储存的,所以如果bones的顺序不同,可能蒙皮动画的结果也千差万别。有些程序员在更换模型时后动画出错就是这里出了问题。
btw:bone对顶点的作用信息,在Mesh类中的boneWeights中设置。

localBounds

localBounds是蒙皮网格的边界框,有些美工或程序在开发过程中,会发现模型莫名其妙在Camera里消失了。通常是这里出了问题,在Camera属性中有个occlusionCulling功能,是对Camera内的网格根据边界框进行裁切,在视锥外的MeshRender是不渲染的。判断条件就是模型的bounds,有些蒙皮动画对模型拉伸,但bounds还是很小,造成Camera不对Mesh进行渲染。updateWhenOffscreen设置成ture是个比较好的解决办法,会实时更新localBounds,但同样会造成性能问题。当然也可以关闭Camera的occlusionCulling,但我不推荐这样做。

BakeMesh

BakeMesh如名,烘焙Mesh,当我们的Mesh根据变形达到我们的想要的形状,之后又不需要继续变形时,可以用这个函数将当前姿态的Mesh网格Bake出来,进行MeshRenderer或者其他处理。

SetBlendShapeWeight

setblendShapeWeight是顶点融合的函数,美工在制作表情动画时通常用的是顶点变形,比如Max中的变形器,比如Maya中的BlendShape等,这些数据以什么形式读取出来呢,就是用这个函数根据Index读取的。

源代码:
        public Dictionary<string, Transform> Bones
        {
            get
            {
                if (bones == null)
                {
                    bones = new Dictionary<string, Transform>();
                    Transform[] trans = transform.FindChild("Bip001").GetComponentsInChildren<Transform>();
                    foreach (Transform tran in trans)
                        bones.Add(tran.name, tran);
                }
                return bones;
            }
        }
        private Dictionary<string, Transform> bones;
        public void LoadSkinnedMesh(SkinnedMeshRenderer origin, SkinnedMeshRenderer target)
        {
            if (origin && target)
            {
                Transform[] bones = new Transform[target.bones.Length];
                for (int i = 0; i < bones.Length; i++)
                    bones[i] = Bones[target.bones[i].name];
                origin.sharedMesh = target.sharedMesh;
                origin.sharedMaterial = target.sharedMaterial;
                origin.bones = bones;
                origin.rootBone = Bones[target.rootBone.name];
            }
        }

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引