真Unity3d_分享一个Animator帮助类

可快速执行动画

本来还是想吐槽一下,不过算了,要是让我重头开发游戏,可能并不会用Animator

Animator作为Unity的官方产品,存在很久,4.6.3版本已经存在,一直没需要更新??历史悠久,版本稳定,优点也很无敌(当然针无两头利,最大的优点永远伴随最大的缺点)

优点:

  • 暂时,可见的最好的可视化状态机(可视化不好被程序员控制,)
  • 提供AnyState (悲剧的开始,不是单向状态机,很靠程序员自律)
  • 向上分多个Layer (同上)
  • 每个状态向下可自定义Behaviours (同上)
  • 提供完整的Animator Controller API (可能底层是c++,每个API都不高级,都不好用,例如hashName等)
  • 一般不出问题 (出了问题就完全不知道哪里入手)

之前花了半天,写了一个Helper,结果一个小弟觉得没用,删了,结果就是各种BUG,各种鬼畜,各种不播动画就是无从解决

这里分享一下之前的Inspector,方便美术使用,能快速发现动作的问题和调试

未必能全支持,但是下面这例子已经足够复杂,各动画均支持快速播放

/* Animator 快速播放
 * 
 * Author:  Sidney
 * Last:    20200404
 *  - created
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;

[CustomEditor(typeof(Animator))]
public class AnimatorInspector : Editor
{
    public class AnimInAnimator
    {
        public string name;
        public AnimatorCondition[] conditions;
        //public AnimatorCondition condition;
    }

    Animator _anim;
    Dictionary<string,AnimInAnimator> _infos;
    AnimatorController _ctl;
    Dictionary<string, AnimatorControllerParameter> _params;
    public bool clearAllState = true;
    GUIStyle normalStyle;
    GUIStyle pressStyle;
    private void Awake()
    {
        _anim = target as Animator;
        InitState();

        //normalStyle = GUIStyle
    }
    void InitState()
    {
        _infos = new Dictionary<string, AnimInAnimator>();
        _ctl = _anim.runtimeAnimatorController as AnimatorController;
        AnimatorStateMachine stateMachine = _ctl.layers[0].stateMachine;
        ChildAnimatorState[] animatorState = stateMachine.states;
        _params = new Dictionary<string, AnimatorControllerParameter>();
       
        foreach (var par in _ctl.parameters)
        {
         
            _params.Add(par.name, par);
        }
        //
        foreach (var anyTransition in stateMachine.anyStateTransitions) {
            AddState(anyTransition);
        }

        for (int i = 0; i < animatorState.Length; i++)
        {
            ChildAnimatorState state = animatorState[i];
          
            var tranitions = state.state.transitions;
            string srcName = state.state.name;
            foreach (var tran in tranitions)
            {
                只有出的transition(没有入??) 所以通过"出"判断
                //string stateName = tran.destinationState.name;
                //if (_infos.ContainsKey(stateName) == false)
                //{
                //    AnimInAnimator data = new AnimInAnimator();
                //    data.name = stateName;
                //    data.conditions = tran.conditions;
                //    _infos.Add(stateName, data);
                //}
                var data = AddState(tran);
                
                //判断出输入transition 所有、、???
                Debug.Log(string.Format("{0}->{1}", srcName, data.name));
            }
  

        }
    }
    AnimInAnimator AddState(AnimatorStateTransition tran) {
        //只有出的transition(没有入??) 所以通过"出"判断
        string stateName = tran.destinationState.name;
        AnimInAnimator data = null;
        if (_infos.ContainsKey(stateName) == false)
        {
            data = new AnimInAnimator();
            data.name = stateName;
            data.conditions = tran.conditions;
            _infos.Add(stateName, data);
        }
        else {
            data = _infos[stateName];
        }
        return data;
    }
    public override void OnInspectorGUI()
    {
        if (!Application.isPlaying)
        {
            GUILayout.Label("运行后,才显示执行动画按钮");

        }
        else
        {
            clearAllState = GUILayout.Toggle(clearAllState, "执行动画前还原Animator参数", new GUILayoutOption[0]);
            foreach (var data in _infos)
            {

                string animation = data.Value.name;
                GUIStyleState s_state = new GUIStyleState();


                string styleName = "button";
                //if (_anim.GetCurrentAnimatorStateInfo(0).fullPathHash == animation)
                //{
                //    s.name = "PreButtonBlue";
                //}
                //详细测试可参考:https://blog.csdn.net/weixin_33896726/article/details/86216606

                if (_anim.GetCurrentAnimatorStateInfo(0).shortNameHash == Animator.StringToHash(animation))
                {
                    styleName = "PreButtonBlue";
                }
                if (GUILayout.Button(animation, styleName))
                {
                    OnClearParams();
                    OnStateButtonClick(data.Value);
                }
            }
        }
        GUILayout.Space(5);
        base.OnInspectorGUI();
    }
    void OnClearParams() {
        if (clearAllState) {
            foreach (var par in _params) {
                AnimatorControllerParameter param = par.Value;
                if (param.type == AnimatorControllerParameterType.Bool)
                {
                    _anim.SetBool(param.name, param.defaultBool);
                }
                else if (param.type == AnimatorControllerParameterType.Float)
                {
                    _anim.SetFloat(param.name, param.defaultFloat);
                }
                else if (param.type == AnimatorControllerParameterType.Int)
                {
                    _anim.SetInteger(param.name, param.defaultInt);
                }
            }
        }
    }
    void OnStateButtonClick(AnimInAnimator data_value)
    {
        if (data_value.conditions == null || data_value.conditions.Length == 0)
        {
            //如果没条件,又想进入这个状态。。。。。
        }
        else
        {
            //_anim.Play(animation);
            foreach (var con in data_value.conditions)
            {
                string key = con.parameter;
                float value = con.threshold;
                var param = _params[key];
                if (param.type == AnimatorControllerParameterType.Bool)
                {
                    if (con.mode == AnimatorConditionMode.If)
                    {
                        _anim.SetBool(key, true);
                    }
                    else
                    {
                        _anim.SetBool(key, false);
                    }

                }
                else if (param.type == AnimatorControllerParameterType.Float)
                {
                    if (con.mode == AnimatorConditionMode.Equals)
                    {
                        _anim.SetFloat(key, value);
                    }
                    else if (con.mode == AnimatorConditionMode.NotEqual)
                    {
                        _anim.SetFloat(key, value + 1);
                    }
                    else if (con.mode == AnimatorConditionMode.Greater)
                    {
                        _anim.SetFloat(key, value);
                    }
                    else if (con.mode == AnimatorConditionMode.Less)
                    {
                        _anim.SetFloat(key, value - 1);
                    }
                    else
                    {
                        Debug.LogError("Animator Set Float 应该不会出现这个情况 mode...=" + con.mode.ToString());
                    }
                }
                else if (param.type == AnimatorControllerParameterType.Int) {
                    if (con.mode == AnimatorConditionMode.Equals || con.mode == AnimatorConditionMode.Greater)
                    {
                        _anim.SetInteger(key, (int)value);
                    }
                    else if (con.mode == AnimatorConditionMode.Less || con.mode == AnimatorConditionMode.NotEqual)
                    {
                        _anim.SetInteger(key, (int)(value - 1));
                    }
                    else
                    {
                        Debug.LogError("Animator Set Int 应该不会出现这个情况 mode...=" + con.mode.ToString());
                    }
                }
                else if (param.type == AnimatorControllerParameterType.Trigger) {
                    _anim.SetTrigger(key);
                }
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

avi9111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值