1. 程式人生 > >用animator控制animation並記錄正播倒播

用animator控制animation並記錄正播倒播

//父級指令碼,掛在animator上

using UnityEngine;

using System.Collections;

public class UIAnimatorParent : MonoBehaviour
{
    //父級指令碼
    //控制動畫時長
    float animTime = 0.1f;
    //停止時間
    float stopTime = 0f;
    //是否開始播放動畫
    bool isStart = false;
    public bool isBacking = false;
    Animator animator;
    string nextAnim;
    public string playName = "";
    private UIAnimator[] allUIA;

    void Awake()
    {
        animator = this.transform.GetComponent<Animator>();
        allUIA = transform.GetComponentsInChildren<UIAnimator>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Z))
        {
            PlayAnimation(playName, 1);
        }
        if (isBacking)
        {
            stopTime -= Time.deltaTime;
            //Debug.Log(animator.playbackTime);
            if (stopTime <= 0f)
            {
                isBacking = false;
                animator.StopPlayback();
                isStart = false;
                if (string.IsNullOrEmpty(nextAnim))
                {

                }
                else
                {
                    PlayAnimation(nextAnim, 1);
                    nextAnim = null;
                }
            }
            return;
        }
        //判斷播放時長是否大於最大動畫時長
        if (isStart)
        {
            if (stopTime > animTime)
            {

                AllStoped();
            }
            else
            {
                stopTime += Time.deltaTime;
            }
        }
    }
    //全部結束
    public void AllStoped()
    {
        isStart = false;
        stopTime = 0;
        animTime = 0.1f;
        //animator.CrossFade("default", 0);
        animator.StopPlayback();
        animator.StopRecording();
        animator.Stop();
        animator.enabled = false;
        for (int i = 0; i < allUIA.Length; i++)
        {
            allUIA[i].StopAnimation();
        }
        if (stopDelegate != null)
        {
            if (callDelegateName == playName)
            {
                stopDelegate();
                ClearDelegate();
            }
        }
        //所有動畫播放完畢回撥,動畫播放完畢後開始正式執行邏輯
    }

    int lastPlayType = 1;
    public delegate void animStoped();
    animStoped stopDelegate;
    string callDelegateName;

    //清除結束回撥
    public void ClearDelegate()
    {
        stopDelegate = null;
        callDelegateName = null;
    }
    //播放動畫
    public void PlayAnimation(string _playName, int type = 1,animStoped delega = null)
    {
        playName = _playName;
        if (lastPlayType == 2)
        {
            AllStoped();
        }
        if (delega != null)
        {
            callDelegateName = playName;
            stopDelegate = delega;
        }
        animator.enabled = true;
        if (type == 1)
        {
            float speed = 1f;
            if (!isStart)
            {
                animator.Play(playName, 0, 0);
                animator.StartRecording(60);
                speed = 1f;
                StartCoroutine(PlayNext(type));
            }
            else
            {
                animator.playbackTime = stopTime;
                animator.StopRecording();
                animator.StartPlayback();
                UIAnimator[] animtionList = transform.GetComponentsInChildren<UIAnimator>();
                for (int i = 0; i < animtionList.Length; i++)
                {
                    if (animtionList[i].ani.isPlaying)
                    {
                        animtionList[i].ani[animtionList[i].animaName].speed = -1;
                    }
                }
                isBacking = true;
                nextAnim = playName;
                speed = -1f;
            }
            animator.speed = speed;
            isStart = true;
        }
        else if (type == 2)
        {
            lastPlayType = 2;
            animator.Play(playName, 0, 0);
            isStart = true;
            StartCoroutine(PlayNext(type));
        }

    }
    //下幀執行,因為動畫play後動畫在下幀才播放
    public IEnumerator PlayNext(int type)
    {
        yield return GamePresident.Instance.oneFrame;
        JudgeTime(animator.GetCurrentAnimatorClipInfo(0)[0].clip.length, type);
    }

    //判斷子動畫時間是否大於整個動畫時長
    public void JudgeTime(float time, int type = 0)
    {
        //大於則重新整理
        if (stopTime + time > animTime)
        {
            animTime = stopTime + time;
        }
    }

}

//子指令碼,掛在animation上

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

[System.Serializable]
public class UIAnimatorInformation
{
    public string parentPlayName;
    public string playName;
}

[RequireComponent(typeof(Animation))]
public class UIAnimator : MonoBehaviour
{
    //父級控制指令碼
    public UIAnimatorParent animParent;
    //父級控制的動畫
    public Animation ani;
    UIAnimator uiani;
    //當動畫有多個的時候啟用
    public List<UIAnimatorInformation> animNameList = new List<UIAnimatorInformation>();
    //動畫時長
    float animfloat;

    //此動畫名稱
    public string animaName;

    // Use this for initialization
    void Awake()
    {
        ani = this.GetComponent<Animation>();
        uiani = this.GetComponent<UIAnimator>();
        AnimationClip aniClip = ani.clip;
        //獲取子動畫時長
        //AnimationEvent ae = new AnimationEvent();
        animParent = transform.GetComponentInParent<UIAnimatorParent>();
        //ae.time = aniClip.length;
        ////增加子動畫結束回撥
        //ae.functionName = "Stoped";
        //aniClip.AddEvent(ae);

    }

    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
    }

    //結束回撥
    public void AnimStoped()
    {
        Debug.Log("AnimStoped!");
        StopAnimation();
    }

    //全播完後執行此方法
    public void StopAnimation()
    {
        ani.enabled = false;
        uiani.enabled = false;
    }
    //控制指令碼開關來控制播放
    void OnEnable()
    {
        ani.enabled = true;
        if (animNameList.Count > 0)
        {
            for (int i = 0; i < animNameList.Count; i++)
            {
                if (animNameList[i].parentPlayName == animParent.playName)
                {
                    animaName = animNameList[i].playName;
                }
            }
        }
        if (animParent.isBacking)
        {
            ani[animaName].speed = -1;
        }
        else
        {
            ani[animaName].speed = 1;
            animParent.JudgeTime(ani.GetClip(animaName).length);
        }
        ani.Play(animaName,PlayMode.StopAll);
        
        //判斷此子動畫的時長從播放到結束是否大於其他所有動畫的時長
        
    }
    public void ClearEvents()
    {
        ani.GetClip(animaName).events = null;
    }
}

//Editor下

//基本字面意思,子物體建立好animation後直接點選我要新增控制子動畫指令碼

//多個的時候要在子指令碼上新增每個動畫所屬animatorClip的名字


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

public class AddAnimatorControlInspector : Editor
{
    public override void OnInspectorGUI()
    {
        base.DrawDefaultInspector();

        if (GUILayout.Button("我要新增控制子動畫指令碼!"))
        {
            Animator parent = (Animator)base.target;
            Animation[] animationList = parent.GetComponentsInChildren<Animation>();
            UIAnimatorParent uiaParent = parent.GetComponent<UIAnimatorParent>();
            if (uiaParent == null)
            {
                parent.gameObject.AddComponent<UIAnimatorParent>();
            }
            for (int i = 0; i < animationList.Length; i++)
            {
                Animation anim = animationList[i];

                UIAnimator uia = anim.transform.GetComponent<UIAnimator>();
                uia.ani = anim;
                uia.animaName = anim.clip.name;
                int cc = 0;
                foreach (AnimationState state in anim)
                {
                    if (uia.animNameList.Count > cc)
                    {
                        uia.animNameList[cc].playName = state.name;
                        cc++;
                    }
                    else
                    {
                        uia = anim.gameObject.AddComponent<UIAnimator>();
                    }
                    //uia.ClearEvents();
                    
                    //bool haveStop = false;
                    //for (int j = 0; j < state.clip.events.Length; j++)
                    //{
                    //    AnimationEvent ste = state.clip.events[j];
                    //    if (ste.functionName == "AnimStoped")
                    //    {
                    //        haveStop = true;
                    //    }
                    //}
                    //if (!haveStop)
                    //{
                    //    AnimationEvent ae = new AnimationEvent();
                    //    ae.time = state.clip.length;
                    //    //增加子動畫結束回撥
                    //    ae.functionName = "AnimStoped";
                    //    AnimationEvent[] aes = { };
                    //    AnimationUtility.SetAnimationEvents(state.clip, aes);
                    //}
                }

                if (uia.animNameList.Count > cc)
                {
                    for (int j = cc; j < uia.animNameList.Count; j++)
                    {
                        uia.animNameList.RemoveAt(j);
                    }
                }
            }
        }
        if (GUILayout.Button("重置所有元件!"))
        {
            Animator parent = (Animator)base.target;
            Animation[] animationList = parent.GetComponentsInChildren<Animation>();
            UIAnimator[] uiaList = parent.transform.GetComponentsInChildren<UIAnimator>();
            parent.enabled = false;
            for (int i = 0; i < animationList.Length; i++)
            {
                animationList[i].enabled = false;
                animationList[i].playAutomatically = false;
            }
            for (int i = 0; i < uiaList.Length; i++)
            {
                uiaList[i].enabled = false;
            }
        }

    }

}

[CanEditMultipleObjects()]
[CustomEditor(typeof(Animator), true)]
public class AddAnimatorControlInspectorP : AddAnimatorControlInspector
{


}

//子Editor

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

public class ChangeAnimationInspector : Editor
{
    public override void OnInspectorGUI()
    {
        base.DrawDefaultInspector();

        if (GUILayout.Button("我要修改子動畫!"))
        {
            Animation thisTransform = (Animation)base.target;
            SaveChangeAnimatorInfo saInfo = thisTransform.transform.GetComponentInChildren<SaveChangeAnimatorInfo>();
            GameObject gobjParent;
            if (saInfo == null)
            {
                gobjParent = new GameObject("gobjParent!");
                saInfo = gobjParent.AddComponent<SaveChangeAnimatorInfo>();
                gobjParent.transform.SetParent(thisTransform.transform);
                
            }
            else
            {
                gobjParent = saInfo.gameObject;
                
            }
            Animator[] animList = thisTransform.GetComponentsInParent<Animator>();
            for (int i = 0; i < animList.Length; i++)
            {
                GameObject gobj = new GameObject("gobj");
                gobj.transform.SetParent(gobjParent.transform);
                UnityEditorInternal.ComponentUtility.CopyComponent(animList[i]);
                UnityEditorInternal.ComponentUtility.PasteComponentAsNew(gobj);
                ChangeAnimatorInfomation caiInfo = gobj.AddComponent<ChangeAnimatorInfomation>();
                caiInfo.belongTo = animList[i].gameObject;
                DestroyImmediate(animList[i]);
            }
        }
        if (GUILayout.Button("我要還原!"))
        {
            Animation thisTransform = (Animation)base.target;
            SaveChangeAnimatorInfo[] saInfoList = thisTransform.transform.GetComponentsInChildren<SaveChangeAnimatorInfo>();
            for (int i = 0; i < saInfoList.Length; i++)
            {
                ChangeAnimatorInfomation[] mationList = saInfoList[i].transform.GetComponentsInChildren<ChangeAnimatorInfomation>();
                for (int j = 0; j < mationList.Length; j++)
                {
                    if (mationList[j].belongTo != null)
                    {

                        UnityEditorInternal.ComponentUtility.CopyComponent(mationList[j].transform.GetComponent<Animator>());
                        Animator componentOld = mationList[j].belongTo.GetComponent<Animator>();

                        if (!componentOld)
                        {
                            UnityEditorInternal.ComponentUtility.PasteComponentAsNew(mationList[j].belongTo);
                        }
                        else
                        {
                            UnityEditorInternal.ComponentUtility.PasteComponentValues(componentOld);
                        }
                    }
                    DestroyImmediate(mationList[j].gameObject);
                }
                DestroyImmediate(saInfoList[i].gameObject);
            }
        }
    }

}

[CanEditMultipleObjects()]
[CustomEditor(typeof(Animation), true)]
public class ChangeAnimationInspectorP : ChangeAnimationInspector
{
 
 
}