Unity3D学习笔记(十八):Animator新动画

新动画系统:
给模型选择动画类型
普通动画:Generic
人形动画:Humanoid
建立动画控制器 - 在Project右击 - 选择Create-AnimatorContorller
将对应动画控制器拖入到Animator的Contorller
双击动画控制器可以打开Animator窗口
将对应动画片段拖入生成新节点,就可以编辑了
橙色节点:相当于旧动画系统的默认片段
灰色节点:
Any State:代表所有动画状态

设置默认片段

建立基础连线

箭头代表两个动画的过渡
Transition Duration:代表融合

任何状态都可以连线到death,甚至包括自己到自己

取消death过渡到自己的选择
动画鬼畜问题,自己过渡到自己
建立过渡条件
添加参数,有4种
通过代码激活参数,实现动画切换

默认过渡条件:Has Exit Time,播放完当前动画才会进行到下一动画的过渡
有条件,取消勾选
无条件,默认勾选,跳跃,浮空
给游戏物体添加脚本,控制参数的激活
代码不能越权:越过动画状态机设置的逻辑(动画连线)的权限
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HellephantAnimator : MonoBehaviour {
    public Animator anim;
       // Use this for initialization
       void Start () {
              
       }
       
       // Update is called once per frame
       void Update () {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            anim.SetBool("isMove", true);
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            anim.SetBool("isMove", false);
        }
        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            anim.SetTrigger("Death");
        }
    }
}
用一个怪物管理器,管理两个怪物的父类
两种方法:
1、管理两个怪物的父类
2、把方法写成接口
父类:全部写成虚函数
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public enum EnemySta
{
    Move,
    Idle,
    Death
}
public class NewMonsterBase : MonoBehaviour {
    public PlayerControl moveTarget;//设置目标点
    public MonsterManager manager;//怪物属于那个管理器
    public virtual void Action()
    {   
    }
    public virtual void Move()
    {      
    }
    public virtual void Idle()
    {       
    }
    public virtual void Damage()
    {      
    }
    public virtual void Death()
    {     
    }
    public virtual void DeathEvent()
    {    
    }
}

这两个需要初始化,要放在父类里

public PlayerControl moveTarget;//设置目标点
public MonsterManager manager;//怪物属于那个管理器

子类:继承父类,并重写父类方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class HellephantControl : NewMonsterBase
{
    public Animator anim;
    public EnemySta enemySta;
    //因为我们需要经常用到目标的状态,所以把TransForm改成了PlayerControl
    public NavMeshAgent navMeshAgent;//引用寻路系统
    private int enemyHealth = 30;//设置怪物生命值
    // Use this for initialization
    void Start()//子类添加新动画系统
    {
        enemySta = EnemySta.Move;
        anim.SetBool("isMove", true);
    }
    // Update is called once per frame
    void Update()
    {
        Action();
    }
    public override void Action()
    {
        switch (enemySta)
        {
            case EnemySta.Move:
                Move();
                break;
            case EnemySta.Idle:
                Idle();
                break;
            case EnemySta.Death:
                Death();
                break;
        }
    }
    public override void Move()
    {
        //anim.CrossFade("Move", 0.2f);
        navMeshAgent.SetDestination(moveTarget.transform.position);
        //如果怪物的目标死了
        if (moveTarget.playSta == PlaySta.Death)
        {
            //寻路停止
            navMeshAgent.isStopped = true;
            //状态切换到闲置
            enemySta = EnemySta.Idle;
            anim.SetBool("isMove", false);
        }
    }
    public override void Idle()
    {
        //anim.CrossFade("Idle", 0.2f);
    }
    public override void Damage()
    {
        //受伤减血
        enemyHealth -= 10;
        //Debug.Log("怪物生命"+enemyHealth);
        //如果血到了0
        if (enemyHealth <= 0)
        {
            //状态变成死亡状态
            enemySta = EnemySta.Death;
            anim.SetTrigger("Death");
            navMeshAgent.isStopped = true;
            gameObject.GetComponent<SphereCollider>().enabled = false;
            //gameObject.tag = "Untagged";
        }
    }
    public override void Death()//子类关闭老动画系统
    {
        //anim.CrossFade("Death", 0.2f);
    }
    public override void DeathEvent()
    {
        //在管理器列表中移除自己
        manager.monsterList.Remove(this);
        //销毁自己
        Destroy(this.gameObject);
    }
}
怪物管理器的怪物列表全部改成父类
怪物管理器的怪物生成
怪物预制体改成数组
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MounsterManager : MonoBehaviour {
    List<Transform> birthPoint;
    public GameObject[] monsterPreGo;
    //最大怪物数
    public int MaxMonsterCount;
    public List<NewMonsterBase> monsterList;
    public NewPlayer player;
       // Use this for initialization
       void Start () {
        birthPoint = new List<Transform>();
        monsterList = new List<NewMonsterBase>();
        //遍历所有的子物体,将其加到出生点列表中
        for (int i = 0; i < transform.childCount; i++)
        {
            birthPoint.Add(transform.GetChild(i));
        }
     
    }
    void CreateMonster() {
        monsterCont++;
        GameObject go;
        if (monsterCont%5==0)
        {
            go = Instantiate<GameObject>(monsterPreGo[1]);
        }
        else
        {
            //实例化一个怪物
             go = Instantiate<GameObject>(monsterPreGo[0]);
        }
       
        //怪物的位置设置任意出生点
        go.transform.position = birthPoint[Random.Range(0, birthPoint.Count)].position;
        //取得怪物脚本
        NewMonsterBase monster = go.GetComponent<NewMonsterBase>();
        //把怪物放到管理器列表里
        monsterList.Add(monster);
        //指定怪物的目标
        monster.moveTarget = player;
        //指定怪物的管理者
        monster.manager = this;
    }
    int monsterCont = 0;
    void CheckMonster() {
        if (monsterList.Count < MaxMonsterCount)
        {
            CreateMonster();
        }
    }
       // Update is called once per frame
       void Update () {
              
       }
    private void FixedUpdate()
    {
        CheckMonster();
    }
}

怪物动画添加死亡检测事件
骨骼动画锁定:只允许动画控制器修改
在动画状态机的设置里,取消骨骼动画锁定

怪物添加碰撞体

新动画系统的新功能
融合树功能:一个和多个参数,来决定播放哪个动画
更改动画类型

动画和模型分开

拖拽模型生成预制体

添加动画控制器

任意窗口最大化:shift+空格
中键拖动,滚轮缩放
动画本身带有位移动画,根据实际情况决定
好处:过渡自然
坏处:代码不可控,代码强拉,会显得不自然
勾选动画自带的位移动画
建立三个动画的融合树
添加参数,保存键值,保证参数正确传递

右键新建 融合树

双击融合树,打开融合树窗口,右键可以再添加融合树

添加motion

第一列:默认融合区间0到1 ,三个动画过渡0,0.5,1
第二列:动画速度
默认融合区间均等分开,取消勾选,可自行修改

旧动画系统修改动画片段的速度

添加脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DefaultAvatarAnimator : MonoBehaviour {
    public Animator anim;
    public int speedHashID;
    public int angleHashID;
    public int attackHashID;
    private float slowSpeed;//速度修正
                            // Use this for initialization
    void Start () {
        speedHashID = Animator.StringToHash("Speed");//哈希Code,效能略高,不用每次调用都转换
        angleHashID = Animator.StringToHash("Angle");
        attackHashID = Animator.StringToHash("Attack");
    }
    // Update is called once per frame
    void Update () {      
        if (Input.GetKey(KeyCode.LeftShift))
        {
            slowSpeed = 0.5F;
        }
        else
        {
            slowSpeed = 1.0F;
        }
        anim.SetFloat(speedHashID, Mathf.Clamp01(Input.GetAxis("Vertical")) * slowSpeed);//Mathf.Clamp01,剔除向后走的值
        anim.SetFloat(angleHashID, Input.GetAxis("Horizontal") * slowSpeed);
        if (Input.GetMouseButtonDown(0))
        {
            anim.SetTrigger(attackHashID);
        }      
       
    }
}

给Walk和Run添加融合树

层级关系
两个动画融合,要和动画师沟通,融合动作容易变形,最后让动画师手动新建动画
边跑动,边射箭
添加Attack层,添加射箭节点,添加Attack参数

点击齿轮,修改层级权重为1

Blending融合模式
Override,两个动作折中,一般选则
Aaditive,两个动作叠加
添加Avatar Mask,阿凡达遮罩
如果动画类型是人形动画:Humanoid,可选择Humanoid的Mask
分配骨骼权重:点击区域激活失活
动画模型来自同一骨骼(同一Avatar)

添加代码

猜你喜欢

转载自www.cnblogs.com/ciaowoo/p/10363077.html