Unity Mesh角色换装与表情动画
发表于2018-11-19
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]; } }