Unity基础(23)-动画系统

2020-06-02 11:52:43 浏览数 (1)

1.png

Unity3D动画系统

分为旧版动画系统和新版动画(Mecanim)系统即Animation 与 Animator

Mecanim概述:

Mecanim是Unity提供第一个丰富而复杂的动画系统,提供了: 针对人形角色的简易的工作流和动画创建能力 Retargeting(运动重定向)功能,即把动画从一个角色模型应用到另一个角色模型上的能力。 针对Animations Clips(动画片段)的简易工作流,针对动画片段及他们之间的过度和交互预览能力。 一个用于管理动画间复杂交互作用的可视化窗口。 通过不同逻辑来控制不同身体部位的运动能力。

Paste_Image.png

1、Animation动画状态机

Animation是U3D旧版的动画状态机,我们一般将模型中的动画放入其中,通过代码开执行动画。

代码语言:javascript复制
// 拿到Animation组件
Animation Ani = GetComponent<Animation>();
// 执行已经放入其中的动画片段
Ani.CrossFade("Walk"); // 默认就是正播
Ani["Walk"].speed = 1f;

Ani["Walk"].speed = -1f; // 如果是-1 那就是倒着播放
Ani.CrossFade("Walk");
2、Animator动画状态机

Paste_Image.png

Paste_Image.png

其实到这里,我们应该想一个角色模型上面有什么?

2-1.U3D角色模型拥有什么属性?

Paste_Image.png

导入进Unity3D的模型属性:

Paste_Image.png

Paste_Image.png

2-2.将制作好的角色模型导入Unity3D中是什么样?

Paste_Image.png

2-3.新的Mecanim动画系统多了什么东西呢?

Paste_Image.png

我们可以看出多了一个普通,标准动画,和一套类人体骨骼动画。

2-4.二者之间有什么区别呢?

Generic: 这是为任何东西像是人,有动画的柱子,四足动物之类设计的。重定向在这里是不支持的,但是你仍然可以得到后文中描述的Mecanim的好处。 Humanoid: Mecanim对于类人角色有一个特别的工作流,使用扩展后的GUI和重定向。配置包含创建和设定一个Avatar并且调整肌肉定义。 类人体骨骼动画就是由Unity3D软件根据动画模型的骨骼系统创建一套自己的Avatar. 何一个拥有avatar的GameObject都将拥有一个Animator组件用来连接角色和他的行为。 Avatar: 是一个将一个角色的骨骼信息重定向到另一个角色上的接口。(下图展示就是一个Avatar) 我们一般查看内部的骨骼有没有错误,或者肌肉的伸展有没有问题.(如果在公司,那么有问题也轮到开发人员去调整,模型师会帮助你完成)

Paste_Image.png

视频教程: http://www.youku.com/playlist_show/id_29528034.html

3、Animator-事件系统
1-添加事件

Paste_Image.png

Paste_Image.png

2-我们添加脚本监听书写的事件方法

方法名字一定要与你请的事件名字一致

Paste_Image.png

Paste_Image.png

注意:在拥有动画状态机的那一级添加脚本才能实现,不然会报错(就是在角色身上添加脚本,实现事件才不会出错)

4、Animator-拆分动画

如果贵公司的UI很认真,那么你就省去大把时间来拆分动画了.如果没有,那么你就需要拆分动画了

Paste_Image.png

1-动画片段其他属性: Apply Root Motion

Paste_Image.png

Bake into Pose

Paste_Image.png

我们首先来看这个“Bake into Pose".在untiy中将动画中的变换分成两种,Body Transform和Root Transform,我们可以设置动画中的关于模型的一些变换(平移、旋转等)是属于Body Transform(pose)还是Root Transform(trajectory)的一部分。这里的Bake into Pose 也就是将变换设置为Body Transform(pose)的一部分。我们可以这样去理解,如果是设置成Body Transform(pose)的话,就相当这些变换是属于动画本身的一部分,也就是说,不管设不设置Apply Root Motion,在场景中,我们都会看到模型位置或角度的变化。(因为Body Transform不影响模型实际的位置和角度,所以这里只是纯粹的动画效果,模型的位置和角度参数值不变),如果设置成Root Transform,Root Transform将影响模型的实际位置和角度(前提是要设置“Apply Root Motion”,如果不设置Apply Root Motion的话,也就是说变换将不应用,场景中的模型位置或角度是不会有变化的(参数值自然也不变),就像一个行走动画,可能一直在原地行走)。 然后我们来重点再看看这里的”Apply Root Motion".这里他会起到两个作用,首先最重要的是,决定是否应用Root Transform,如果应用的话,那么在动画的同时,模型的位置和角度会同时跟着变化。如果这里不勾选的话,那么就是说不应用Root Transform,这样我们所有的Root Transform都将不起任何作用。(也就相当于于所有没有Bake into Pose 的变换都没有用了)。 Apply Root Motion的第二个作用是在动画结束后,将Body Transform中的变化应用到模型(注意,这里是结束的时候才应用,也就是说动画的时候,模型的position、rorate等参数是不变的,当动画结束之后,开始新的动画之前才会改变,注意这里跟前面提到的Root Transform的区别)

1、勾选”Bake into Pose",不勾选“Apply Root Motion",勾选”Bake into Pose"后,变换属于Body Transform,所以即使这里未勾选”Apply Root Motion“,但是动画依然会在场景中体现,人物会按照动画的路径行走(但是如果我们观察Inspector中模型的position参数,值一直不变)。但是因为没有勾选Apply Root Motion,所以动画结束后,变换不会应用到模型,所以如果这时候,如果开始一个新的动画的话,模型会瞬间回到起始位置(新的动画开始时候,模型处于行走动画开始时的位置)。

2、勾选”Bake into Pose",并勾选“Apply Root Motion",这里跟上面的情况唯一不同的就是,动画结束后,开始新的动画之前,变换会应用到模型。(模型的position在新的动画开始之前会发生变化,新的动画开始时候,模型处于动画结束时的位置)

3、不勾选”Bake into Pose",勾选“Apply Root Motion",这时候,变换是作为Root Transform,所以因为这里勾选了Apply Root Motion,变换会应用到模型(模型的position跟着动画不停的变化),自然,新的动画开始时候,模型处于动画结束时的位置。

4、不勾选”Bake into Pose",并且不勾选“Apply Root Motion",这里变化还是作为Root Transform,但是因为没有勾选Apply Root Motion,所以变换将不被应用,所以模型将一直在本地不动,自然,新的动画开始时候,模型处于行走动画开始时的位置

视频教程: http://www.youku.com/playlist_show/id_29528034.html 详细介绍,参考:http://blog.csdn.net/cubesky/article/details/39478207

5、Animator-动画状态机,动画控制器
1、手动创建(动画控制器)AnimatorController:

Paste_Image.png

Paste_Image.png

还可以这样打开:

Paste_Image.png

2、代码创建(动画控制器)AnimatorController:
代码语言:javascript复制
using System.Collections;
using UnityEditor;
using UnityEditor.Animations;//5.0改变 UnityEditorInternal;并不能用了。
 
public class CreateAnimatorController : Editor 
{
    [MenuItem("ModelConfig/创建Controller")]
    static void DoCreateAnimationAssets()
    {
        //创建Controller
        AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath("Assets/animation.controller");
        //得到它的Layer
        AnimatorControllerLayer layer = animatorController.layers[0];
        //将动画保存到 AnimatorController中
        AddStateTransition("Assets/Art Resources/Character/moster-002/basic/moster-002@run.FBX", layer);
        AddStateTransition("Assets/Art Resources/Character/moster-002/basic/moster-002@stand.FBX", layer);
        AddStateTransition("Assets/Art Resources/Character/moster-002/basic/moster-002@born.FBX", layer);
    }
 
    private static void AddStateTransition(string path, AnimatorControllerLayer layer)
    {
        AnimatorStateMachine sm = layer.stateMachine;
        //根据动画文件读取它的AnimationClip对象
        AnimationClip newClip = AssetDatabase.LoadAssetAtPath(path, typeof(AnimationClip)) as AnimationClip;
        
        ////取出动画名子 添加到state里面
        AnimatorState state = sm.AddState(newClip.name);
        //5.0改变
        state.motion = newClip;
        Debug.Log(state.motion);
        //把state添加在layer里面
        AnimatorStateTransition trans = sm.AddAnyStateTransition(state);
    }
}

补充: inspector有一个debug模式,你在debug模式下修改一下Animation Type为0 就可以了 Unity有两套Animation系统,一套是legacy,一套是Mecanim。 Debug模式下的Animation Type 0表示Mecanim,可以用于animator;1表示Legacy,用于animation组件。

之前已经写过两套的动画系统,今天主要分享关于动画层的使用及注意事项

这个就是层的概念

6、为什么动画中会有层的概念

其实在新版的动画状态机中,大量的技巧已经让一般的小白晕头转向了。而且就目前来说:使用状态机的单一层动画就已经可以满足日常开发需要。那么为什么出现层的概念呢? 先来几张图,对比一下,你就会发现哪里好

其实我们已经可以发现这种好处了,类似项目管理

第一:分离动画组 第二:规范动画制作 第三:提供更丰富的动画制作 Ps:其实跟我们的动画融合树差不多。。。

2.如何使用层动画?

01-添加动画层

添加层

注意:同一时刻我们只能执行一个层的动画片段。 02-添加参数

Paste_Image.png

注意:参数是执行动画的触发条件

03-给第二层的触发线绑定参数

Paste_Image.png

绑定的过程中,其实我们会发现New State就代指第一层动画组,而参数帮助我们过渡了层。当然动画是显示不出来的,但是动画片段确实执行了。

3.注意点?

在动画层之间切换的过程中,其实主要是通过参数的满足与否来进行层动画执行操作,但是有一个前提就是层的权重 如下图:

权重问题决定动画能不能显示出来

如果不设置权重,你会发现即便分好层,而且在状态机中发现动画执行了,但是界面的角色并没有显示出来。

前面的分享已经提到过使用代码控制动画的参数,这里如何通过代码设置权重呢?

代码语言:javascript复制
    [SerializeField]
    private Animator ani;
    void Start () {
        // 表示设置动画第二层的权重为1
        ani.SetLayerWeight(1, 1);
    }

视频教程: http://www.youku.com/playlist_show/id_29528034.html

方反向运动学

7、反向动力学:IK
1:什么是反向动力学?

一般我们都是通过父节点来调动子节点运动,而在实际开发过程中,有时候我们需要子节点带动父节点进行相应的动作。这种情况就是反向动力学。其实在国内的游戏中很少看见IK动画,一般而言国外的游戏较多。例如刺客信条,手部带动身体的爬行。 通俗讲:使用场景中的各种物体来控制和影响角色身体部位的运动

2:IK能做什么?

一般来说,我们在特定的场景下,需要我们的游戏对象一起看向某一个游戏环境或者游戏其他对象。而这个时候,反向运动学就可以让我们很好的做到这种效果。

3:案例介绍

上图的案例就是游戏人物盯着某个游戏对象看,来达到时刻注视的效果。 首先打开IK开关

打开开关会显示IK字样

代码语言:javascript复制
    [SerializeField]
    private Animator ani;
    public GameObject target;
    void Start() {
        // 表示设置动画第二层的权重为1
        ani.SetLayerWeight(1, 1);
    }
    // 特定方法
    void OnAnimatorIK(int layerIndex)
    {
        ani.SetLookAtWeight(1);
        //身体的IK就是 参数
       // ani.SetLookAtWeight(1,1,1,1);
        if (target.transform != null)
        {
            ani.SetLookAtPosition(target.transform.position);
        }

更复杂一点,就是让身体也跟着注释的对象移动或摆动

代码语言:javascript复制
    [SerializeField]
    private Animator ani;
    public GameObject target;
    public Transform leftVec;
    public Quaternion qua;
    void Start() {
        // 表示设置动画第二层的权重为1
        ani.SetLayerWeight(1, 1);
        //mask.positionXYZWeight = new Vector3(0,1,1);
        //mask.rotationWeight = 1;                    
       }


    void Update() {
        qua = Quaternion.Euler(target.position);
    }
    void OnAnimatorIK(int layerIndex)
    {
        ani.SetLookAtWeight(1);
        if (target.transform != null)
        {
            ani.SetLookAtPosition(target.transform.position);
        }
        // 设置左手的IK
        ani.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
        ani.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
        if(leftVec != null)
        {
            ani.SetIKPosition(AvatarIKGoal.LeftHand, target.transform.position);
            ani.SetIKRotation(AvatarIKGoal.LeftHand, qua);
        }
    }
}

投篮姿势

复杂一点,根据动画来约束游戏对象的身体某一部位到达指定位置

代码语言:javascript复制
    public Animator ani;
    public Transform LeftHand;
    bool hasJump = false;
    void Start () {
        ani = GetComponent<Animator>();
    }
    
    
    void Update () {
        if (ani)
        {
            AnimatorStateInfo info = ani.GetCurrentAnimatorStateInfo(0);
            
            if (Input.GetKeyDown(KeyCode.Space))
            {
                ani.SetBool("Jump", true);
              
            }
            if (info.IsName("Base Layer.Vault"))
            {
                ani.SetBool("Jump", false);
                // 第一个参数动作位置,第二个参数角色旋转,第三个是做动作的某个身体部位,第四个是权重信息,第五六参数是获取动画曲线
                ani.MatchTarget(LeftHand.position, LeftHand.rotation, AvatarTarget.LeftFoot, new MatchTargetWeightMask(new Vector3(1, 1, 1), 0), ani.GetFloat("StartA"), ani.GetFloat("EndA"));
                hasJump = true;
            }
        }
    }
}
4:IK相关的插件

Paste_Image.png

FinalIK,这个我没有研究过,但听说效果不错。可以去看看,官方商店是有的,有机会研究吧。。。

视频教程: http://www.youku.com/playlist_show/id_29528034.html

8、TimeLine使用

0 人点赞