学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为2477字,预计阅读6分钟

前言

在《Unity3D使用Cinemachine配合Timeline实现运镜效果》一篇中我们已经实现了简单的运镜效果,这一篇还是利用TimeLine做动画,然后通过事件触发,实现一个过场动画的效果。

unity人物动画条件切换 unity场景切换动画_html

实现效果

unity人物动画条件切换 unity场景切换动画_unity3d_02

从上图中我们可以看到,利用TimeLine做了两个动画效果,一个是进门的动画,一个是出门的动画,其中除了门打开,人物跑动进入和出去,还有Cinemachine实现的镜头切换。

创建项目

unity人物动画条件切换 unity场景切换动画_unity人物动画条件切换_03

微卡智享

01

创建项目

unity人物动画条件切换 unity场景切换动画_web_04

unity人物动画条件切换 unity场景切换动画_html_05

新建了一个Unity3D的项目,我们直接在资源商店下载了两个免费资源Anime Character : Arisa (Free)和School assets

unity人物动画条件切换 unity场景切换动画_web_06

导入了学校的场景后,再把我们的人物也放入到场景之中,如上图显示。

02

设置触发事件的门

unity人物动画条件切换 unity场景切换动画_unity人物动画条件切换_07

上图中我们找到要触发事件的门,然后在门上加了一个Text的显示,在门中找到对应的Cube后看其本身就是一个MeshCollider,在这个Cube上我们调整旋转中Y的值,改90或是-90就可以令门进行打开或是关闭,这样我们在做TimeLine时通过调整这个Cube的Y轴旋转即可实现开关门的效果了。

03

设置Cinemachine

unity人物动画条件切换 unity场景切换动画_unity3d_08

新建一个空物体改名为Camera,然后在上面创建两个Cinemachine虚拟摄像机,其中CMPlayer绑定在人物下面的MainCamera中,并且设置为3rd Person Follow第三人称跟随。

unity人物动画条件切换 unity场景切换动画_html_09

CMMath的虚拟摄像机设置在进门后教室的位置,镜头的朝着门的方向看。

04

设置TimeLine动画

unity人物动画条件切换 unity场景切换动画_web_10

打开窗口里时间轴的界面,界面中创建一个空物体起名为TimeLine,然后在其下面再创建两个空物体分别是MathIn和MathOut,用于创建进门和出门的两个动画。

unity人物动画条件切换 unity场景切换动画_web_11

点击MathIn后在时间轴内点Create后,设置对应的保存目录及文件名,左边的时间轴就可以开始进行编辑了。

unity人物动画条件切换 unity场景切换动画_html_12

在MathIn里面开始编辑动画,上图中可以看到,我们先设置了Cinemathine的两个摄像机切换,然后Player的下面有两个动画,一个是人物的动作(分为平常动画和跑动动画),另一个是人物的位置移动。最后下面黄色框中说明的是我们的Cube_10也就是门的动画,这里就是通过修改其Y轴的旋转,实现开门和关门的效果。

完成这些动画的时间最关键的是上图中蓝框中关键帧的位置,也就是说是时间线,大概在多少帧做什么动作,每个动画前面的红色圆点点击后就是录制的功能,点开后设置其关键帧的位置后,设置对应的当前相关参数。

unity人物动画条件切换 unity场景切换动画_unity3d_13

上面动图中可以看到设置Timeline的整个流程,这样我们就是把两个动画通过这样的方式完成了,时间轴上有一个播放按钮,如果开头的实现效果中的动画那样,在每次设置时都可以进行播放看看效果。

05

脚本编辑

上面的动画已经完成后,我们就可考虑到下一步怎么实现触发动画了,现在只做了一个门的触发,后面需要加上不能的教室播放不同的效果,所以这里播放动画的脚本应该挂载到人物身上,通过人物碰撞检测,用于判断播放哪个动画,进门和出门的动画因为不同,所以也要考虑到现在的状态是进门还是出门,用来判断播放不同的动画。

unity人物动画条件切换 unity场景切换动画_web_14

在Scripts脚本下创建了两个C#的脚本,一个是DoorController脚本控制碰撞时播放的动画,另一个PlayerStatus脚本用于处理判断人物进入的哪个门的状态。

PlayerStatus

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


public class PlayerStatus
{
    public Dictionary<string, bool> classroom;


    public PlayerStatus()
    {
        classroom = new Dictionary<string, bool>();
        classroom.Add("Math", false);
    }


}

里面加入一个为Dictionary<string, bool>的属性,在实例化时加入了数学Math的类,后面的bool值用于判断现在是在教室里还是教室外。

DoorController

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Playables;


public class DoorController : MonoBehaviour
{
    private PlayerStatus status = null;


    public List<Transform> timelines;


    // Start is called before the first frame update
    void Start()
    {
        status = new PlayerStatus();


        //获取TimeLine下所有设置好的动画
        GameObject go = GameObject.Find("TimeLine");
        timelines = go.GetComponentsInChildren<Transform>(true).ToList();
    }


    private void OnCollisionEnter(Collision collision)
    {
        //获取到碰撞体的标签值
        string tagname = collision.gameObject.tag;
        string playname = string.Empty;
        switch (tagname)
        {
            //当标签是数学,根据是否在教室内判断播放的动画
            case "Math":
                playname = status.classroom[tagname] ? "MathOut" : "MathIn";
                
                break;
        }


        //判断是否可以播放TimeLine
        if (!string.IsNullOrEmpty(playname))
        {
            StartCoroutine(PlayTimeLine(playname, tagname));
        }
    }


    IEnumerator PlayTimeLine(string name,string tagname)
    {
        PlayableDirector director = timelines.Find(t => t.name == name).GetComponent<PlayableDirector>();
        director.Play();


        yield return new WaitForSeconds(2f);
        //播放完后修改进屋状态
        status.classroom[tagname] = !status.classroom[tagname];
    }


}

DoorController中我们实例化了PlayerStatus,然后在Start()中把TimeLine中下面的PlayableDirctor都加载进来,在OnCollisionEnter事件中通过判断碰撞体的标签,对应PlayerStatus中的值来判断当前应该播放的动画,然后使用协程的方式进行在加载好的PlayableDirctor列表中找到对应的播放动画进行播放。播放完后再修改PlayerStatus的状态。

06

绑定脚本及触发

unity人物动画条件切换 unity场景切换动画_unity3d_15

把我们编辑好的DoorController脚本添加到人物组件中。

unity人物动画条件切换 unity场景切换动画_unity3d_16

然后在门的Cube_10的组件中标签页添加一个Math的标签,这个值和PlayerStatus类中的stirng值要一样,如果这里不设置的话,当人物碰撞到门的时候会什么也不触发。