1. 程式人生 > >Unity 編輯器下控制播放Animator

Unity 編輯器下控制播放Animator

     在Unity編輯器的Scene檢視進行控制播放Animator,可以藉助方法StartPlayback、StopPlayback、StartRecording和StopRecording,具體可以參照以下例子:

  建立一個帶 Controller的Animator物件,可以看到此時人物呈現T型姿勢。附上新指令碼 EditAnimator,此為空指令碼,如下:  C# Code 
1
2
3
4
5
6
  using UnityEngine;

public  class EditAnimator : MonoBehaviour 
{
}
建立一個這個指令碼的編輯器類 EditAnimatorInspector,程式碼如下:  C# Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  using UnityEditor;
using UnityEngine;

[CustomEditor( typeof(EditAnimator))]
public  class EditAnimatorInspector : Editor
{
     /// <summary>
     /// 滑動杆的當前時間
     /// </summary>
     private  float m_CurTime;
    
     /// <summary>
     /// 是否已經烘培過
     /// </summary>
     private  bool m_HasBake;
    
     /// <summary>
     /// 當前是否是預覽播放狀態
     /// </summary>
     private  bool m_Playing;

     /// <summary>
     /// 當前執行時間
     /// </summary>
     private  float m_RunningTime;
    
     /// <summary>
     /// 上一次系統時間
     /// </summary>
     private  double m_PreviousTime;
    
     /// <summary>
     /// 總的記錄時間
     /// </summary>
     private  float m_RecorderStopTime;

     /// <summary>
     /// 滑動杆總長度
     /// </summary>
     private  const  float kDuration = 30f;

     private Animator m_Animator;

     private EditAnimator editAnimator { get {  return target  as EditAnimator; } }

     private Animator animator
    {
        get {  return m_Animator ?? (m_Animator = editAnimator.GetComponent<Animator>()); }
    }

     void OnEnable()
    {
        m_PreviousTime = EditorApplication.timeSinceStartup;
        EditorApplication.update += inspectorUpdate;
    }

     void OnDisable()
    {
        EditorApplication.update -= inspectorUpdate;
    }

     public  override  void OnInspectorGUI()
    {
        EditorGUILayout.BeginHorizontal();
         if (GUILayout.Button( "Bake"))
        {
            m_HasBake =  false;
            bake();
        }
         if (GUILayout.Button( "Play"))
        {
            play();
        }
         if (GUILayout.Button( "Stop"))
        {
            stop();
        }
        EditorGUILayout.EndHorizontal();
        m_CurTime = EditorGUILayout.Slider( "Time:", m_CurTime, 0f, kDuration);
        manualUpdate();
    }

     /// <summary>
     /// 烘培記錄動畫資料
     /// </summary>
     private  void bake()
    {
         if (m_HasBake)
        {
             return;
        }

         if (Application.isPlaying || animator ==  null)
        {
             return;
        }

         const  float frameRate = 30f;
         const  int frameCount = ( int)((kDuration * frameRate) +  2);
        animator.Rebind();
        animator.StopPlayback();
        animator.recorderStartTime =  0;

         // 開始記錄指定的幀數
        animator.StartRecording(frameCount);

         for (var i =  0; i < frameCount -  1; i++)
        {
             // 這裡可以在指定的時間觸發新的動畫狀態
             if (i ==  200)
            {
                animator.SetTrigger( "Dance");
            }

             // 記錄每一幀
            animator.Update( 1.0f / frameRate);
        }
         // 完成記錄
        animator.StopRecording();

         // 開啟回放模式
        animator.StartPlayback();
        m_HasBake =  true;
        m_RecorderStopTime = animator.recorderStopTime;
    }

     /// <summary>
     /// 進行預覽播放
     /// </summary>
     private  void play()
    {
         if (Application.isPlaying || animator ==  null)
        {
             return;
        }

        bake();
        m_RunningTime = 0f;
        m_Playing =  true;
    }

     /// <summary>
     /// 停止預覽播放
     /// </summary>
     private  void stop()
    {
         if (Application.isPlaying || animator ==  null)
        {
             return;
        }

        m_Playing =  false;
        m_CurTime = 0f;
    }

     /// <summary>
     /// 預覽播放狀態下的更新
     /// </summary>
     private  void update()
    {
         if (Application.isPlaying || animator ==  null)
        {
             return;
        }

         if (m_RunningTime > m_RecorderStopTime)
        {
            m_Playing =  false;
             return;
        }

         // 設定回放的時間位置
        animator.playbackTime = m_RunningTime;
        animator.Update( 0);
        m_CurTime = m_RunningTime;
    }

     /// <summary>
     /// 非預覽播放狀態下,通過滑桿來播放當前動畫幀
     /// </summary>
     private  void manualUpdate()
    {
         if (animator && !m_Playing && m_HasBake && m_CurTime < m_RecorderStopTime)
        {
            animator.playbackTime = m_CurTime;
            animator.Update( 0);
        }
    }

     private  void inspectorUpdate()
    {
        var delta = EditorApplication.timeSinceStartup - m_PreviousTime;
        m_PreviousTime = EditorApplication.timeSinceStartup;

         if (!Application.isPlaying && m_Playing)
        {
            m_RunningTime = Mathf.Clamp(m_RunningTime + ( float)delta, 0f, kDuration);
            update();
        }
    }
}
檢視器效果如下:   點選" Bake",可以看到此時人物姿勢變成了動畫狀態的第一幀,如下所示:   拖動滑桿,即可播放當前時間的那一幀,如下所示:   點選" Play",即可以自動播放整個動畫,如下所示:  

再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智慧的隊伍中來!https://www.cnblogs.com/captainbed