当前位置:  开发笔记 > 编程语言 > 正文

检索所有Animator状态并在代码中手动设置它们

如何解决《检索所有Animator状态并在代码中手动设置它们》经验,为你挑选了1个好方法。

我偶然发现了一些我从未想过的问题,但是...确实如此。我正在使用unity 5.5编写visualiazion / simulation工具箱。

使用的模型已经导入,并且通过编辑器设置了动画剪辑。这是我的动画状态控制器的外观:

我想在DropdownMenu中显示AnimationStates。每当用户选择一项时,当前动画状态都应设置为所选状态。

eG用户选择了自动播放:将状态设置为剪辑自动播放,然后设置为SimpleRotate,然后设置为ComplexRotate,然后再次设置为自动播放(只是一个简单的循环)。

但是,如果用户选择“空闲”,“ ComplexRotate 0”或“ SimpleRotate 0”,则动画应播放一次,然后停留在剪辑的结尾。(就像我在动画控制器中所做的一样。

这是我想要的一个相当伪的版本:

//Retrieve all states to populate the dropdown:
List states = myAnimationController.GetAllStates();

foreach(AnimationState state in states)
  Dropdown.add(state.name)


//callback
OnDropdownIndexChanged(int item)
{
  string stateName = ..... //removed for simplicity
  myAnimationController.setState(stateName)
}

最重要的是,如果我可以检查FROM和TO状态之间的转换,那就太好了。(自动播放是应该在循环的下拉菜单中显示的唯一状态)

可以通过自定义动画控制器实现此功能吗?还是我错过了什么?



1> 小智..:

我在这里看到两个选择。一个相当简单的工具,但是比较复杂,但是功能强大。

选项一

您使用RuntimeAnimatorController。这将在运行时为您提供给定Animator中的所有AnimationClip。您可以使用随时在AnimatorController中播放State Animator.Play(StateNameOrHash)。不幸的是,这个选项,这样只会通过其名称或NameHash(如statet发挥国家文档)。因为我们只有AnimationClipsController的State而没有States,所以此选项涉及将Controller中的State重命名为Animation Clip的确切名称。然后,您可以播放一个像这样的状态:

myAnimator.Play(myAnimationClip.name);

这是一个入门的快速选择,但从长远来看不是一个好的选择,因为它本质上有两个缺点:

您只能在AnimatorController中使用平面层次结构。没有SubStateMachines / Blendtree,因为它们没有以表示AnimationClip。因此,您将无法通过检索这些国家,RuntimeAnimatorController因为它只会返回AnimationClips

AnimatorController可能很难理解,因为状态命名为AnimationClips。我在这里不了解您的情况,但是最好使用描述性名称,然后使用AnimationClips中的名称,以更好地理解。

选项二

这个选项比较复杂。我将为您提供工作流程的快速概述,然后更详细地解释各部分或提供参考以帮助您入门!

    [Editor Script]从AnimatorController生成包含所有状态的脚本。(可能是“最难的”部分)

    使用生成的脚本用状态填充您的下拉菜单

    发挥你的状态:)

第1部分: 使用编辑器脚本从AnimatorController中提取所有状态。此链接应为您提供有关如何实现此目的的提示。简短(未经测试)的示例代码:

private void writeAllStates()
{
    AnimatorControllerLayer[] allLayer = controller.layers;

    List stateNames = new List();

    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);
}

请记住:所使用的AnimatorController是内部UnityEditor.Animations的命名空间。这可以是EditorScript中的公共字段,以轻松为您提供访问权限。

第2部分:您的脚本文件应创建一个类似于该类的类:

public class AnimatorControllerStates
{
    public List states = new List
    {
        "Idle",
        "ComplexRotate 0",
        "Autoplay",
        ...
    }
}

将该类命名为与您为其创建的AnimatorController相关的类。并将此类作为运行时脚本中的一个字段。然后,您可以像这样访问所有状态:

myAnimatorControllerStates.states

该数组可以填充您的下拉列表。您将保存下拉列表的索引,然后可以通过索引播放状态。

第3部分:现在,只需在脚本中播放状态就非常容易了:

string state = myAnimatorControllerStates.states[mySelectedIndex];
myAnimatorController.Play(mySelectedIndex);

我不知道您的项目范围,但是要拥有一个可维护的应用程序,我随时都希望选择第二种方法。

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有