Unity 中使用 Animator 控制 BlendShape 的 AnimationClip 播放

本文深入解析Unity中AnimatorController的三层表情动画系统:FaceLayer、FaceBlinkLayer与FaceMouthLayer,探讨精细表情与基本元件的制作方法,及解决blendshape动画与多层混合时的常见问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 Animato Controller 中分成 3 层

(1) FaceLayer 表情基本层,主要是各种基本表情

(2) FaceBlinkLayer 表情眨眼,这个一般是在一个基本表情播放完成后,然后间隔眨眼

(3) FaceMouthLayer 口型

表情制作可能分

(1)

精细表情,这个就是整个表情和口型都是在 Animation 或者 Max 中 Key 帧中制作出来。在 FaceLayer 播放,播放完成后,在 FaceBlinkLayer 播放眨眼

(2)

基本元件,制作几种基本元件,类似哭、笑、生气等几种,然后使用这几种播放,在 FaceLayer  播放,播放完成,在 FaceBlinkLayer 间隔播放眨眼

animator controller 中遇到的问题

(1)

播放一个 blendshape 的 animationclip ,如果当前的 animationclip 没有播放完,直接播放下一个 animationclip ,会导致 blendshape 权重设置错误,口型卡主之类的

解决方法

将 blendshape 权重值全部重置初始值,然后再进行下一个 animationclip 的播放

animator controller 中多层遇到的问题

(1)

FaceLayer 中没有设置 MouthA 这个 blendshape 权重,FaceMouthLayer 设置 MouthA 这个权重,但是多层混合后,MouthA 却不是 FaceMouthLayer 设置的 MouthA 权重

解决方法

将 FaceMouthLayer 的混合方式从 Addition 改成 Override

其它层

(2)

问题

(2.1)

动画是播放了部分,例如眼睛转动没有播放,可能是 mask 不对的问题

 

只要添加对应的骨骼就可以了

(2.2)

blendshape 突然不起作用了,可能是 blendshape 动画导出的时候没有了

应该是

只要重新导出就可以了

(2.3)

(6)

Animator Controller 配置

(6.1)

这三层必须要有,名字必须是对应的名字

(6.2)

每一层的 Layer 名字,状态名字,动画名字必须是这个,程序要使用这些名字去替换资源

(6.3)

每一层 Mask 设置

 

(6.4)

新建对应的 AvatarMask

AvatarMask 设置

Humanoid 设置

Transform 目前只设置这几个

 

(6.5)

Prefab 上挂组件,Blink List 是随机从数组中挑选眨眼动画播放, Interval 是播放眨眼间隔, AvatarName 对应的是 Assets\AsbRes\Emotion\Mei 目录下的名字,不同 Avatar 配置不同名字,根据这个去查找资源

 

 

 

### 如何在 Unity 中获取 Blend Shape 的相关信息或操作方法 在 Unity 中,可以通过 `SkinnedMeshRenderer` 组件来访问和修改模型中的 Blend Shapes。以下是具体的实现方法: #### 获取 Blend Shape 名称及其权重 通过 `GetBlendShapeName(int index)` 和 `GetBlendShapeWeight(int index)` 方法可以从指定索引处获取 Blend Shape 的名称和当前权重。 ```csharp using UnityEngine; public class BlendShapeController : MonoBehaviour { SkinnedMeshRenderer skinnedMeshRenderer; void Start() { skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>(); if (skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null) { int blendShapeCount = skinnedMeshRenderer.sharedMesh.blendShapeCount; // 获取 Blend Shape 总数 for (int i = 0; i < blendShapeCount; i++) { string name = skinnedMeshRenderer.GetBlendShapeName(i); // 获取 Blend Shape 名称 float weight = skinnedMeshRenderer.GetBlendShapeWeight(i); // 获取 Blend Shape 当前权重 Debug.Log($"Blend Shape Name: {name}, Weight: {weight}"); } } } } ``` 上述代码展示了如何遍历并打印所有 Blend Shapes 的名称和权重[^1]。 --- #### 设置 Blend Shape 权重 通过 `SetBlendShapeWeight(int index, float value)` 方法可以设置特定 Blend Shape 的权重(范围为 0 到 100)。以下是一个示例: ```csharp void SetBlendShapeWeightExample() { if (skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null) { int targetIndex = 0; // 替换为目标 Blend Shape 的索引 float newWeight = 50f; // 新的权重 skinnedMeshRenderer.SetBlendShapeWeight(targetIndex, newWeight); Debug.Log($"Set Blend Shape at Index {targetIndex} to Weight {newWeight}"); } } ``` 此代码片段演示了如何更改某个 Blend Shape 的权重[^2]。 --- #### 使用 Animator 控制 Blend Shape 动画 当需要将 Blend Shapes 集成到动画系统中时,推荐使用 UnityAnimator Controller。Animator 提供了一个简单的方法来跨状态平滑过渡 Blend Shapes 的权重。例如,可以利用 `CrossFade` 函数完成这一目标: ```csharp Animator animator; void InitializeAnimator() { animator = GetComponent<Animator>(); } void PlayBlendShapeAnimation() { if (animator != null) { string animationStateName = "Happy"; // 替换为实际的状态名 float transitionDuration = 0.5f; // 过渡时间 animator.CrossFade(animationStateName, transitionDuration); } } ``` 这里展示了如何通过 Animator 平滑切换至不同的表情动画状态[^3]。 --- #### 实现 LookAt 效果与 Blend Shape 结合 为了使角色的眼睛跟随目标物体转动,通常会结合 IK(Inverse Kinematics)技术以及 Blend Shapes 完成更加自然的效果。下面是一段基于眼球骨骼旋转角度映射到 Blend Shape 权重的逻辑: ```csharp private AnimationCurve curve = new AnimationCurve(); // 自定义曲线调整权重比例 void UpdateEyeBlendShapes(Transform eyeBone, Vector3 lookTargetPosition) { if (eyeBone == null || skinnedMeshRenderer == null) return; // 计算眼睛看向的目标方向 Vector3 directionToTarget = (lookTargetPosition - eyeBone.position).normalized; Quaternion targetRotation = Quaternion.LookRotation(directionToTarget); // 更新眼球骨骼朝向 eyeBone.rotation = Quaternion.Slerp(eyeBone.rotation, targetRotation, Time.deltaTime * rotationSpeed); // 将旋转角度转换为 Blend Shape 权重 float angle = Vector3.Angle(Vector3.forward, directionToTarget); float mappedValue = Mathf.Clamp(curve.Evaluate(angle), 0f, 100f); // 应用到对应的 Blend Shape 上 int blinkIndex = GetBlinkBlendShapeIndex(); skinnedMeshRenderer.SetBlendShapeWeight(blinkIndex, mappedValue); } ``` 该函数实现了根据眼球骨骼的角度动态调整 Blink Blend Shape 的权重[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值