58.3D动画分层和遮罩

58.3D动画-动画分层和遮罩


58.1 知识点

动画分层的主要目的

动画分层的作用

  • 游戏中会有这样的需求
  • 人物健康状态时播放正常动画
  • 人物非健康状态时播放特殊动画
  • 比如血量低于一定界限,人物的大部分动作将表现为虚弱状态
  • 我们可以利用动画分层来快速实现这样的功能

动画分层和动画遮罩结合使用

  • 3D游戏中我们常常会面对这样的需求
  • 人物站立时会有开枪动作
  • 人物跑动时会有开枪动作
  • 人物蹲下时会有开枪动作
  • 从表现上来看光是开枪动作可能就有3种
  • 如果要让美术同学做3种开枪动作费时又费资源
  • 我们是否可以这样做
  • 比如开枪动画只影响上半身
  • 下半身根据实际情况播放站立,跑动,蹲下动作
  • 通过上下半身播放不同的动画就可以达到动画的组合播放

动画分层的两个目的

  • 两套不同层动作的切换
  • 结合动画遮罩让两个动画叠加在一起播放
  • 提升动画多样性,节约资源

如何使用动画分层

新建一个动画层

设置动画层参数


Weight 权重

当动画同时播放时,如果选择的是叠加状态,会根据权重决定叠加的比例

Mask 动画遮罩

该层动画全部都会受该遮罩的影响
可以在创建遮罩文件并赋值给这个参数

遮罩文件可以设置不受影响的区域,动画播的时候不收影响的区域就没效果。这个和模型文件的Animation页签下的选项效果一样,不过只影响这一层。

Blending 混合方式


Override:覆盖方式,播放该层动画时忽略其他层信息
Additive:叠加方式,会和其它层动画叠加播放

Sync 是否同步其它层


主要用于直接从另一个层复制状态过来,在该层中进行修改
适用于比如正常状态下有待机走路跑步等等动作,但是受伤状态下动作会改变,可以利用同步层方便我们进行编辑
选择后会多一个Source Layer表示你要复制哪一层的状态
比如直接复制普通层1,修改上面的动画选项为蹲下的待机和走路,这样调大这一层的权重就会播放蹲下的待机和走路

Timing 源层

当选中Sync同步其它层时,该参数激活
选中,会采用折中方案调整同步层上的动画时长(基于权重计算)
不选中,动画时长将使用原始层做为母版

IK Pass IK处理

反向动力学,之后讲解IK的时候再讲解

在该层中设置状态机

注意:结合遮罩使用时默认状态一般为Null状态,空动画不会关联任何动画剪辑

可以创建新的空状态作为一层的默认播放动画,这样就算该层有权重也不会有任何影响

根据需求创建动画遮罩

动画层权重代码控制

Animator.SetLayerWeight方法 设置动画层权重

//Animator中的设置动画层权重GetLayerIndex方法
animator.SetLayerWeight(animator.GetLayerIndex("MyLayer2"), 1);

总结

  • 利用动画分层我们可以做到
  • 上下半身播放两个动画进行组合,比如上半身扔炸弹,下半身待机移动蹲下
  • 快速制作正常状态和受伤状态的动作切换

58.2 知识点代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson58_3D动画_动画分层和遮罩 : MonoBehaviour
{
    private Animator animator;

    void Start()
    {
        #region 知识点一 动画分层的主要目的
        //动画分层的作用
        //游戏中会有这样的需求
        //人物健康状态时播放正常动画
        //人物非健康状态时播放特殊动画
        //比如血量低于一定界限,人物的大部分动作将表现为虚弱状态
        //我们可以利用动画分层来快速实现这样的功能

        //动画分层和动画遮罩结合使用
        //3D游戏中我们常常会面对这样的需求
        //人物站立时会有开枪动作
        //人物跑动时会有开枪动作
        //人物蹲下时会有开枪动作
        //从表现上来看光是开枪动作可能就有3种
        //如果要让美术同学做3种开枪动作费时又费资源

        //我们是否可以这样做
        //比如开枪动画只影响上半身
        //下半身根据实际情况播放站立,跑动,蹲下动作
        //通过上下半身播放不同的动画就可以达到动画的组合播放

        //动画分层的主要就是达到这两个目的
        //1.两套不同层动作的切换
        //2.结合动画遮罩让两个动画叠加在一起播放
        //提升动画多样性,节约资源
        #endregion

        #region 知识点二 如何使用动画分层
        //1.新建一个动画层
        //2.设置动画层参数
        //3.在该层中设置状态机(注意:结合遮罩使用时默认状态一般为Null状态)
        //4.根据需求创建动画遮罩
        animator = this.GetComponent<Animator>();

        //Animator中的设置动画层权重GetLayerIndex方法
        animator.SetLayerWeight(animator.GetLayerIndex("MyLayer2"), 1);

        #endregion

        #region 总结
        //利用动画分层我们可以做到
        //1.上下半身播放两个动画进行组合,比如上半身扔炸弹,下半身待机移动蹲下
        //2.快速制作正常状态和受伤状态的动作切换
        #endregion
    }

}

58.3 练习题

在之前练习题的基础上,按J键可以让人物上半身播放一个其他动画

创建新的一层动画,权重设置为1。创建动画遮罩设置屏蔽的下半身并关联。在这一层添加一个空动画设置成默认播放

添加播放上半身动画参数,进行连线关联

添加控制的代码

if (Input.GetKeyDown(KeyCode.J))
    animator.SetTrigger("Fall");

为角色制作受伤时,基础动画改变的功能

创建新的层,源层关联第一层,动画剪辑设置为受伤时的相关动画,比如受伤的走路,受伤的默认

代码控制层级的权重

if (Input.GetKeyDown(KeyCode.K))
    animator.SetLayerWeight(animator.GetLayerIndex("New Layer 0"), 1);
if (Input.GetKeyDown(KeyCode.L))
    animator.SetLayerWeight(animator.GetLayerIndex("New Layer 0"), 0);

58.4 练习题代码

// 引用命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 定义一个名为 Lesson58_练习题 的类,并继承 MonoBehaviour
public class Lesson58_练习题 : MonoBehaviour
{

    // 声明私有变量 animator,类型为 Animator,表示当前游戏对象的动画控制器
    private Animator animator;

    // 声明公有变量 roundSpeed,类型为 float,表示角色旋转的速度
    public float roundSpeed = 30;

    // 在 Start 函数中获取当前游戏对象的动画控制器
    void Start()
    {
        animator = this.GetComponent<Animator>();
    }

    // 在 Update 函数中实现功能
    void Update()
    {
        // 使用 animator.SetInteger 设置动画控制器中名为 "Speed" 的参数值,使用 Input.GetAxisRaw 获取垂直方向的按键输入
        animator.SetInteger("Speed", (int)Input.GetAxisRaw("Vertical"));

        // 如果空格键被按下,则设置名为 "Jump" 的布尔类型参数为 true
        if (Input.GetKeyDown(KeyCode.Space))
            animator.SetBool("Jump", true);

        // 根据水平方向的按键输入和旋转速度值,绕着 Y 轴旋转当前游戏对象
        this.transform.Rotate(Vector3.up, Input.GetAxisRaw("Horizontal") * roundSpeed * Time.deltaTime);

        #region 练习题一

        // 如果按键 J 被按下,则设置名为 "Fall" 的触发器为 true
        if (Input.GetKeyDown(KeyCode.J))
            animator.SetTrigger("Fall");

        #endregion

        #region 练习题二

        // 如果按下键 K,则设置动画控制器中名为 "New Layer 0" 的 Layer 权重值为 1
        if (Input.GetKeyDown(KeyCode.K))
            animator.SetLayerWeight(animator.GetLayerIndex("New Layer 0"), 1);

        // 如果按下键 L,则设置动画控制器中名为 "New Layer 0" 的 Layer 权重值为 0
        if (Input.GetKeyDown(KeyCode.L))
            animator.SetLayerWeight(animator.GetLayerIndex("New Layer 0"), 0);

        #endregion
    }

    // 声明公有函数 JumpOver,用于在动画结束时将名为 "Jump" 的布尔类型参数设置为 false
    public void JumpOver()
    {
        animator.SetBool("Jump", false);
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏