zoukankan      html  css  js  c++  java
  • 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)

    添加代码

  • 相关阅读:
    Codefroces 920F SUM and REPLACE(线段树)
    POJ 2155 Matrix (2维树状数组)
    POJ 3067 Japan (树状数组求逆序对)
    Codeforces 919D Substring (拓扑排序+树形dp)
    拓扑排序
    Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)
    线段树扫描线(2---算矩形的相交面积)
    线段树扫描线(1---算矩形的总面积)
    hdu 6168 Numbers
    Educational Codeforces Round 27 A B C
  • 原文地址:https://www.cnblogs.com/vuciao/p/10363077.html
Copyright © 2011-2022 走看看