我在这里看到两个选项。一个相当简单的一个,一个更复杂但强大的一个。
选项一
您使用RuntimeAnimatorController
. 这将在运行时为您提供给定 Animator 中的所有 AnimationClip。您可以在任何给定时间使用 AnimatorController 在 AnimatorController 中播放状态Animator.Play(StateNameOrHash)
。不幸的是,对于这个选项,这只会通过其 Name 或 NameHash 播放 State(如docs中的 statet )。因为我们只有控制器中的AnimationClips
状态而不是状态,所以这个选项将涉及将控制器中的状态重命名为动画剪辑的确切名称。然后你可以玩这样的状态:
myAnimator.Play(myAnimationClip.name);
这是一个快速入门的选择,但从长远来看不是一个好的选择,因为它基本上有两个缺点:
- 您只能在 AnimatorController 中使用平面层次结构。没有 SubStateMachines/Blendtrees,因为它们没有用
AnimationClip
. 因此,您将无法通过 检索这些状态,RuntimeAnimatorController
因为它只返回AnimationClips
- AnimatorController 可能很难理解,因为状态的名称类似于
AnimationClips
. 我不知道您的情况,但最好使用描述性名称然后使用 AnimationClips 中的名称以便更好地理解。
选项二
这个选项更复杂。我将为您提供工作流程的快速概述,然后更详细地解释这些部分或提供参考以帮助您入门!
- [Editor Script] 从 AnimatorController 生成包含所有状态的脚本。(可能是“最难”的部分)
- 使用生成的脚本来填充你的下拉列表
- 发挥你的状态:)
第 1 部分:
使用编辑器脚本从 AnimatorController 中提取所有状态。此链接应为您提供有关如何实现此目的的提示。简短(未测试)示例代码:
private void writeAllStates()
{
AnimatorControllerLayer[] allLayer = controller.layers;
List<string> stateNames = new List<string>();
for (int i = 0; i < allLayer.Length; i++)
{
ChildAnimatorState[] states = allLayer[i].stateMachine.states;
for (int j = 0; j < states.Length; j++)
{
// you could do additional filtering here. like "would i like to add this state to my list because it has no exit transition" etc
if (shouldBeInserted(states[i]))
{
// add state to list
stateNames.Add(states[j].state.name);
}
}
}
// now generate a textfile to write all the states
FileGenerator.createFileForController(controller, stateNames);
}
请记住: usedAnimatorController
在UnityEditor.Animations
命名空间内。这可以是 EditorScript 中的公共字段,以便您轻松访问。
第 2 部分:您的脚本文件应该创建一个像这样的类:
public class AnimatorControllerStates
{
public List<string> states = new List<string>
{
"Idle",
"ComplexRotate 0",
"Autoplay",
...
}
}
将类命名为与您创建它的 AnimatorController 有某种关联。并使此类成为您的运行时脚本中的一个字段。然后你可以像这样访问你所有的状态:
myAnimatorControllerStates.states
该数组可以填充您的下拉列表。您将保存下拉列表的索引,然后可以通过索引播放状态。
第 3 部分:现在在脚本中播放您的状态非常容易:
string state = myAnimatorControllerStates.states[mySelectedIndex];
myAnimatorController.Play(mySelectedIndex);
我不知道您的项目的范围,但要拥有一个可维护的应用程序,我随时都希望选项二。