如何在Unity3d中实现MAYA的BlendShape

各位看官,大家好!本小白最近游走在Unity和MAYA中,发现Unity3d(以下简称U3D)可以支持MAYA的BlendSahpe(关于其他三维软件的BlendShape还没有测试)。本文接下来会详细介绍具体的导出设置和导入后如何进行控制。 首先科普下BlendShape(只针对于木有接触过三维动画的人,如果非常熟悉请直接略过)。本想在百度上找一篇相对比较官方的解释,但发现度娘不乐意告诉,无奈只能去老外那里搜点资料。果然皇天不负有心人,还真被我找到啦。不过要为难那些英语不是很好的朋友们啦,因为原文时英文的,本小白最近略忙,后续会为大家奉上翻译版。BlendShape相关资料。总的来说BlendShape是用于变形物体的一种特殊方式,在三维动画领域常用于做表情动画,当然也可以用来做一些非常规动画效果。

首先打开MAYA,创建一个CUBE(此处模型相对比较简单,只是使用了CUBE并简单调了一下点的位置,主要是为了说明原理和步骤。本小白相信各位伟大的看官艺术家肯定能做出比本小白好得多的效果)。CRTL+D(复制)一份,调节一下复制品的顶点。截图如下。

《如何在Unity3d中实现MAYA的BlendShape》

之后先选中Deformable物体,再选中Base物体(此处的顺序非常重要,一定要先选择变形物体,在选择基础物体,否则之后创建的变形效果也会反过来)点击菜单栏Create Deformers > BlendShape(若没有此菜单请切换到Animation模块再尝试),此步骤截图如下。

《如何在Unity3d中实现MAYA的BlendShape》

创建成功后,选择基础物体(也即非变形物体)执行File > ExportSelection选择FBX格式,关于选项有几点需要说明: 1)激活Animation选项; 2)在其下激活Deformed Models; 3)下面继续看激活Deformed Models及其下的Skins与Blenshapes,最后选择Export。设置详情见下图。《如何在Unity3d中实现MAYA的BlendShape》

之后切换到U3D中,新建一个工程,导入我们从MAYA中导出的FBX文件。选中模型在ImportSettings中设置合适的ScaleFactor,其余选项可以暂时保持默认或者根据您的需要进行调节。本小白比较懒,所以保持默认啦。之后关键的来啦。。。。。。。。 将导入的模型从Projec中拖动到Hierachy中,可以看到在Inspector中Skinned Mesh Renderer组件中(小白有些不太明白为何此处会被成为Skinned Mesh Renderer,明明模型中没有包含Bone。莫非U3D会把所有非Transform动画都当做Skinned Mesh????? 不过咱们不纠结这些东西),在BlendShapes下会有一个默认的属性,本小白的被成为“blendShape1.pCube2”,这是U3D默认的起得属性名,本小白在此又犯懒啦,所以没有改。望各位看官见谅。现在可以调节该属性即可在Viewport中看到BlendShape的效果。对于基础相对薄弱的看官看到此处就OK啦,对于有强烈求知欲的看官,请您接着往下看。 通过上面的步骤我们可以通过属性控制BlendShape。那么问题来啦,我们能否在游戏运行过程中动态更改呢?答案必须是肯定的,要不然各位看官该打小白啦。小白想到的思路有两种:1)通过关键帧动画和动画状态机结合来控制BlendShape。(对于小白这种非程序员出身的人来说似乎足够啦,但是作为CSDN这么高大上的地方只有界面操作而没有程序似乎没有那么高大上,故此又继续进一步,研究了一下脚本);2)使用脚本动态控制。由于小白使用的时C#,还烦请各位JS看官自行脑补。脚本如下(由于第一次在CSDN这么高大上的地方发表文章还没搞清楚怎么添加脚本,见谅见谅)。

using UnityEngine;  
using System.Collections;  
  
public class BlendShape : MonoBehaviour {  
      
    // 此处用于控制融合的速度  
    public float blendSpeed = 1;  
      
    // 定义与BlendShape相关的组件  
    private SkinnedMeshRenderer skinMesh;  
    private Mesh mesh;  
      
    void Awake() {  
        // 获取与BlendShape相关的组件  
        skinMesh = GetComponent<SkinnedMeshRenderer>();  
        mesh = skinMesh.sharedMesh;  
        // Debug.Log(skinMesh.GetBlendShapeWeight(0));  
        // Debug.Log(mesh.blendShapeCount);  
    }     
      
    void Update() {  
        // 通过简单的Lerp函数来进行BlendShape权重的渐变  
        if(skinMesh.GetBlendShapeWeight(0) <= 100) {  
            float weight = Mathf.Lerp(skinMesh.GetBlendShapeWeight(0), 100, Time.deltaTime * blendSpeed);  
            skinMesh.SetBlendShapeWeight(0, weight);  
        }  
    }  

 

可能有些看官会有疑问,为什么此处的最大值时100,而不是1.这就是小白最后要说的一个注意点啦。各位看官还记不记得我们之前刚导入模型到U3D时设置了ScaleFactor。这个设置会影响BlendShape的权重参数(blendShape1.pCube2)。小白的ScaleFactor设置成了100,故此处的参数也会同样缩放到0-100的范围。 在结束之前,稍微总结那么一下下:从SkinnedMeshRender组件中获取BlendShape的权重属性,当BlendShape多余1个时还需要从Mesh中拿到blendShapeCount属性 在最后给大家链接了一个官方给出的更加复杂的例子,供各位看官参考。官方例子

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注