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",即可以自动播放整个动画,如下所示:

Unity中的`Transform.AddComponent<Animator>()`用于向一个GameObject添加Animator组件,这是控制该GameObject动画行为的关键组件。Animator组件需要与Animator Controller相连接才能实际控制动画,Animator Controller是一个定义动画状态机的资产文件,它可以包含多个动画状态以及它们之间的转换规则。 要使用代码添加动画控制器,你需要先创建一个Animator Controller资产,并将其分配给Animator组件。这通常通过以下步骤实现: 1. 首先在Unity编辑器中创建一个Animator Controller资源,例如命名为"MyAnimatorController.controller"。 2. 然后编写脚本来在运行时给GameObject添加Animator组件,并将创建好的Animator Controller资源分配给该组件。以下是一个简单的示例代码: ```csharp using UnityEngine; public class AddAnimatorController : MonoBehaviour { void Start() { // 创建Animator Controller资源的路径 string animatorControllerPath = "Assets/Resources/MyAnimatorController.controller"; // 加载Animator Controller资源 AnimatorController controller = Resources.Load<AnimatorController>(animatorControllerPath); // 确保加载成功 if (controller != null) { // 向当前GameObject添加Animator组件 Animator animator = gameObject.AddComponent<Animator>(); // 将加载好的Animator Controller赋值给Animator组件 animator.runtimeAnimatorController = controller; } else { Debug.LogError("Animator Controller not found at path: " + animatorControllerPath); } } } ``` 请注意,上述代码假设你已经将Animator Controller资源放置在了正确的路径下,并且已经将其放置在了Resources文件夹中,这样使用Resources.Load方法才能正确加载。此外,确保Animator Controller资源的名称与脚本中的名称匹配。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值