Пример #1
0
        private BlendTree(AssetLayout layout, AssetInfo assetInfo, AnimatorController controller, StateConstant state, int nodeIndex) :
            base(layout)
        {
            AssetInfo       = assetInfo;
            ObjectHideFlags = HideFlags.HideInHierarchy;

            VirtualSerializedFile virtualFile = (VirtualSerializedFile)assetInfo.File;
            BlendTreeNodeConstant node        = state.GetBlendTree().NodeArray[nodeIndex].Instance;

            Name = nameof(BlendTree);

            Childs = new ChildMotion[node.ChildIndices.Length];
            for (int i = 0; i < node.ChildIndices.Length; i++)
            {
                Childs[i] = new ChildMotion(virtualFile, controller, state, nodeIndex, i);
            }

            BlendParameter         = node.BlendEventID == uint.MaxValue ? string.Empty : controller.TOS[node.BlendEventID];
            BlendParameterY        = node.BlendEventYID == uint.MaxValue ? string.Empty : controller.TOS[node.BlendEventYID];
            MinThreshold           = node.GetMinThreshold(controller.File.Version);
            MaxThreshold           = node.GetMaxThreshold(controller.File.Version);
            UseAutomaticThresholds = false;
            NormalizedBlendValues  = node.BlendDirectData.Instance.NormalizedBlendValues;
            BlendType = node.BlendType;
        }
        void ReplaceAnimationClips(BlendTree blendtree)
        {
            if ((blendtree == null) || (blendtree.children.Length == 0))
            {
                return;
            }

            if (blendtree.children[0].motion is AnimationClip)
            {
                int           length      = blendtree.children.Length;
                ChildMotion[] newChildren = new ChildMotion[length];
                for (int i = 0; i < length; i++)
                {
                    newChildren[i]        = blendtree.children[i];
                    newChildren[i].motion = GetCorrespondingClip((AnimationClip)blendtree.children[i].motion);
                }

                blendtree.children = newChildren;
            }
            else
            {
                foreach (ChildMotion child in blendtree.children)
                {
                    ReplaceAnimationClips(child.motion as BlendTree);
                }
            }
        }
Пример #3
0
        protected AnimatorState CreateLandingState(AnimatorController controller, AnimatorStateMachine stateMachine)
        {
            AnimatorState landingState = stateMachine.AddState("Landing", new Vector3(450, 100, 0));

            BlendTree landingBlendTree = new BlendTree();

            landingBlendTree.name = "Landing";
            landingBlendTree.useAutomaticThresholds = false;
            landingBlendTree.blendParameter         = "LandDamageAmount";

            ChildMotion[] childMotions = new ChildMotion[2];

            childMotions[0].motion    = landingClip;
            childMotions[0].timeScale = 1f;
            childMotions[0].threshold = 0f;

            childMotions[1].motion    = landingDamageClip;
            childMotions[1].timeScale = 1f;
            childMotions[1].threshold = 1f;

            landingBlendTree.children = childMotions;

            AssetDatabase.AddObjectToAsset(landingBlendTree, controller);
            landingBlendTree.hideFlags = HideFlags.HideInHierarchy;

            landingState.motion = landingBlendTree;

            return(landingState);
        }
Пример #4
0
        private void ValidateLayerBlendTree(int index, AnimatorControllerLayer layer, AnimatorController controller)
        {
            string blendTreeName = string.Format(BlendTreeName, index);

            if (layer.stateMachine.states.All(s => s.state.name != blendTreeName))
            {
                Debug.Log($"Layer missing blend tree. {blendTreeName}");
                DeleteObjectFromController(controller, blendTreeName);
                AddBlendTree(index, layer, controller);
            }
            else
            {
                Debug.Log($"Layer Blend Tree Validated {blendTreeName}.");

                BlendTree blendTree = layer.stateMachine.states.FirstOrDefault(s => s.state.name == blendTreeName).state.motion as BlendTree;

                // Just re-assign since ChildMotions aren't their own ScriptableObjects.
                ChildMotion childMotion0 = new ChildMotion
                {
                    motion    = _clips0[index],
                    timeScale = 1
                };
                ChildMotion childMotion1 = new ChildMotion
                {
                    motion    = _clips100[index],
                    timeScale = 1
                };
                blendTree.children = new ChildMotion[2] {
                    childMotion0, childMotion1
                };

                AssetDatabase.SaveAssets();;
            }
        }
            public static ChildMotion DeepClone(this ChildMotion child)
            {
                ChildMotion output = new ChildMotion
                {
                    cycleOffset          = child.cycleOffset,
                    directBlendParameter = child.directBlendParameter,
                    mirror    = child.mirror,
                    position  = child.position,
                    threshold = child.threshold,
                    timeScale = child.timeScale,
                    motion    = (child.motion != null && child.motion.GetType() == typeof(BlendTree)) ? ((BlendTree)child.motion).DeepClone() : child.motion
                };

                return(output);
            }
            public static BlendTree DeepClone(this BlendTree tree)
            {
                BlendTree output = new BlendTree();

                EditorUtility.CopySerialized(tree, output);

                ChildMotion[] children = new ChildMotion[tree.children.Length];
                for (int i = 0; i < children.Length; i++)
                {
                    children[i] = tree.children[i].DeepClone();
                }
                output.children = children;

                return(output);
            }
Пример #7
0
            public ChildMotionJson(ChildMotion childMotion, Urho3DEngine engine, PrefabContext prefabContext)
            {
                this.cycleOffset = childMotion.cycleOffset;
                var motion = childMotion.motion;

                if (motion is AnimationClip animationClip)
                {
                    this.animationClip = engine.EvaluateAnimationName(animationClip, prefabContext);
                    engine.ScheduleAssetExport(animationClip, prefabContext);
                }
                else if (motion is BlendTree blendTree)
                {
                    this.hasBlendTree = true;
                    this.blendTree    = new BlendTreeJson(blendTree, engine, prefabContext);
                }
            }
        private static void ApplyBlendTreeChanges(BlendTree tree, AnimationClipSwap[] treeMotions)
        {
            var newChildren = new ChildMotion[tree.children.Length];

            for (int i = 0; i < tree.children.Length; i++)
            {
                ChildMotion child = tree.children[i];
                if (child.motion is BlendTree childTree)
                {
                    ApplyBlendTreeChanges(childTree, treeMotions[i].TreeMotions);
                }
                else
                {
                    child.motion = treeMotions[i].Motion;
                }

                newChildren[i] = child;
            }
            tree.children = newChildren;
        }
Пример #9
0
        protected AnimatorState CreateGroundedState(AnimatorController controller, AnimatorStateMachine stateMachine)
        {
            // Grounded
            AnimatorState groundedState = stateMachine.AddState("Grounded", new Vector3(300, 0, 0));

            BlendTree groundedMotionBlendTree = new BlendTree();

            groundedMotionBlendTree.name = "Movement";
            groundedMotionBlendTree.useAutomaticThresholds = false;
            groundedMotionBlendTree.blendParameter         = "Forward";

            ChildMotion[] childMotions = new ChildMotion[4];

            childMotions[0].motion    = walkBackwardClip;
            childMotions[0].timeScale = reverseWalkBackAnimation ? -1 : 1;
            childMotions[0].threshold = -0.5f;

            childMotions[1].motion    = idleClip;
            childMotions[1].timeScale = 1;
            childMotions[1].threshold = 0f;

            childMotions[2].motion    = walkForwardClip;
            childMotions[2].timeScale = 1;
            childMotions[2].threshold = 0.5f;

            childMotions[3].motion    = runClip;
            childMotions[3].timeScale = 1;
            childMotions[3].threshold = 1f;


            groundedMotionBlendTree.children = childMotions;

            AssetDatabase.AddObjectToAsset(groundedMotionBlendTree, controller);
            groundedMotionBlendTree.hideFlags = HideFlags.HideInHierarchy;

            groundedState.motion = groundedMotionBlendTree;

            return(groundedState);
        }
        void TraverseClips(BlendTree output)
        {
            if ((output == null) || (output.children.Length < 1))
            {
                return;
            }

            ChildMotion[] dstChildren = output.children;

            AnimationClip clip;

            // Let user know of empty blend trees..
            if (dstChildren.Length < 1)
            {
                AddResult(string.Format("BlendTree \"{0}\" is empty.", output.name), MessageType.Error);
            }

            for (int i = 0; i < dstChildren.Length; i++)
            {
                ChildMotion child = dstChildren[i];

                if (child.motion is AnimationClip)
                {
                    clip = TryGetReplacementClip(child.motion as AnimationClip, output);

                    child.motion   = clip;
                    dstChildren[i] = child;                     // because struct,
                }
                else
                {
                    // blend tree has seeds
                    TraverseClips(child.motion as BlendTree);
                }
            }

            output.children = dstChildren;
        }
Пример #11
0
        private void AddBlendTree(int index, AnimatorControllerLayer layer, AnimatorController controller)
        {
            string controllerPath = AssetDatabase.GetAssetPath(controller);
            string blendTreeName  = string.Format(BlendTreeName, index);

            AnimatorState state = layer.stateMachine.AddState(blendTreeName);

            state.speed = 1;

            BlendTree blendTree = new BlendTree
            {
                name           = blendTreeName,
                blendType      = BlendTreeType.Simple1D,
                blendParameter = AvaCryptKeyNames[index],
            };

            ChildMotion childMotion0 = new ChildMotion
            {
                motion    = _clips0[index],
                timeScale = 1
            };
            ChildMotion childMotion1 = new ChildMotion
            {
                motion    = _clips100[index],
                timeScale = 1
            };

            blendTree.children = new ChildMotion[2] {
                childMotion0, childMotion1
            };

            state.motion = blendTree;
            AssetDatabase.AddObjectToAsset(blendTree, controllerPath);

            AssetDatabase.SaveAssets();
        }
Пример #12
0
    /*
     * [MenuItem("Assets/Export Mecanim Animation Controller", false, 301)]
     * private static void CreateAnimatorFile() {
     * var animatorController = Selection.activeObject as AnimatorController;
     * if (animatorController == null) {
     *  return;
     * }
     *
     * CreateAsset(animatorController);
     * }
     *
     * [MenuItem("Assets/Export Mecanim Animation Controller", true)]
     * private static bool CreateAnimatorController() {
     * return Selection.activeObject is AnimatorController;
     * }
     */

    //  public static AnimatorGraphAsset Fetch(string name) {
    //    AnimatorGraphAsset output = null;

    //#if UNITY_EDITOR
    //    string pathToAnimationResource = "Assets/Resources/DB/Animator/";
    //    string animationFilePath = pathToAnimationResource + name + ".asset";
    //    output = UnityEditor.AssetDatabase.LoadAssetAtPath(animationFilePath, typeof(AnimatorGraphAsset)) as AnimatorGraphAsset;

    //    if (output == null) {
    //      output = CreateInstance<AnimatorGraphAsset>();
    //      animationFilePath = UnityEditor.AssetDatabase.GenerateUniqueAssetPath(animationFilePath);
    //      UnityEditor.AssetDatabase.CreateAsset(output, animationFilePath);
    //      UnityEditor.AssetDatabase.SaveAssets();
    //      UnityEditor.AssetDatabase.Refresh();
    //    }
    //#endif

    //    if (output != null) {
    //      if (output.Settings == null)
    //        output.Settings = new AnimatorGraph();
    //    }

    //    return output;
    //  }

    public static void CreateAsset(AnimatorGraphAsset dataAsset, AnimatorController controller)
    {
        if (!controller)
        {
            return;
        }

        if (!dataAsset)
        {
            return;
        }

        QuantumRunner.Init();//make sure we can get debug calls from Quantum
        dataAsset.controller = controller;
        int weightTableResolution = (int)dataAsset.weight_table_resolution;
        int variableCount         = controller.parameters.Length;

        dataAsset.Settings.variables = new AnimatorVariable[variableCount];

        //Mecanim Parameters/Variables
        //make a dictionary of paramets by name for use when extracting conditions for transitions
        Dictionary <string, AnimatorControllerParameter> parameterDic = new Dictionary <string, AnimatorControllerParameter>();

        for (int v = 0; v < variableCount; v++)
        {
            AnimatorControllerParameter parameter = controller.parameters[v];
            parameterDic.Add(parameter.name, parameter);
            AnimatorVariable newVariable = new AnimatorVariable();

            newVariable.name  = parameter.name;
            newVariable.index = v;
            switch (parameter.type)
            {
            case AnimatorControllerParameterType.Bool:
                newVariable.type        = AnimatorVariable.VariableType.Bool;
                newVariable.defaultBool = parameter.defaultBool;
                break;

            case AnimatorControllerParameterType.Float:
                newVariable.type      = AnimatorVariable.VariableType.FP;
                newVariable.defaultFp = FP.FromFloat_UNSAFE(parameter.defaultFloat);
                break;

            case AnimatorControllerParameterType.Int:
                newVariable.type       = AnimatorVariable.VariableType.Int;
                newVariable.defaultInt = parameter.defaultInt;
                break;

            case AnimatorControllerParameterType.Trigger:
                newVariable.type = AnimatorVariable.VariableType.Trigger;
                break;
            }

            dataAsset.Settings.variables[v] = newVariable;
        }

        //Mecanim State Graph
        int layerCount = controller.layers.Length;

        dataAsset.clips.Clear();
        dataAsset.Settings.layers = new AnimatorLayer[layerCount];
        for (int l = 0; l < layerCount; l++)
        {
            AnimatorLayer newLayer = new AnimatorLayer();
            newLayer.name = controller.layers[l].name;
            newLayer.id   = l;

            int stateCount = controller.layers[l].stateMachine.states.Length;
            newLayer.states = new Quantum.AnimatorState[stateCount + 1];//additional element for the any state
            Dictionary <UnityEditor.Animations.AnimatorState, Quantum.AnimatorState> stateDictionary = new Dictionary <AnimatorState, Quantum.AnimatorState>();

            for (int s = 0; s < stateCount; s++)
            {
                UnityEditor.Animations.AnimatorState state = controller.layers[l].stateMachine.states[s].state;
                Quantum.AnimatorState newState             = new Quantum.AnimatorState();
                newState.name        = state.name;
                newState.id          = state.nameHash;
                newState.isDefault   = controller.layers[l].stateMachine.defaultState == state;
                newState.speed       = FP.FromFloat_UNSAFE(state.speed);
                newState.cycleOffset = FP.FromFloat_UNSAFE(state.cycleOffset);

                if (state.motion != null)
                {
                    AnimationClip clip = state.motion as AnimationClip;
                    if (clip != null)
                    {
                        dataAsset.clips.Add(clip);
                        AnimatorClip newClip = new AnimatorClip();
                        newClip.name    = state.motion.name;
                        newClip.data    = Extract(clip);
                        newState.motion = newClip;
                    }
                    else
                    {
                        BlendTree tree = state.motion as BlendTree;
                        if (tree != null)
                        {
                            int childCount = tree.children.Length;

                            AnimatorBlendTree newBlendTree = new AnimatorBlendTree();
                            newBlendTree.name        = state.motion.name;
                            newBlendTree.motionCount = childCount;
                            newBlendTree.motions     = new AnimatorMotion[childCount];
                            newBlendTree.positions   = new FPVector2[childCount];
                            newBlendTree.weights     = new FP[childCount];

                            string parameterXname = tree.blendParameter;
                            string parameterYname = tree.blendParameterY;
                            for (int v = 0; v < variableCount; v++)
                            {
                                if (controller.parameters[v].name == parameterXname)
                                {
                                    newBlendTree.blendParameterIndex = v;
                                }
                                if (controller.parameters[v].name == parameterYname)
                                {
                                    newBlendTree.blendParameterIndexY = v;
                                }
                            }

                            for (int c = 0; c < childCount; c++)
                            {
                                ChildMotion   cMotion = tree.children[c];
                                AnimationClip cClip   = cMotion.motion as AnimationClip;
                                newBlendTree.positions[c] = new FPVector2(FP.FromFloat_UNSAFE(cMotion.position.x), FP.FromFloat_UNSAFE(cMotion.position.y));

                                if (cClip != null)
                                {
                                    dataAsset.clips.Add(cClip);
                                    AnimatorClip newClip = new AnimatorClip();
                                    newClip.data            = Extract(cClip);
                                    newClip.name            = newClip.clipName;
                                    newBlendTree.motions[c] = newClip;
                                }
                            }


                            FP val = FP._0 / 21;
                            newBlendTree.CalculateWeightTable(weightTableResolution);

                            newState.motion = newBlendTree;
                        }
                    }
                }
                newLayer.states[s] = newState;

                stateDictionary.Add(state, newState);
            }

            //State Transistions
            //once the states have all been created
            //we'll hook up the transitions
            for (int s = 0; s < stateCount; s++)
            {
                UnityEditor.Animations.AnimatorState state = controller.layers[l].stateMachine.states[s].state;
                Quantum.AnimatorState newState             = newLayer.states[s];
                int transitionCount = state.transitions.Length;
                newState.transitions = new Quantum.AnimatorTransition[transitionCount];
                for (int t = 0; t < transitionCount; t++)
                {
                    AnimatorStateTransition transition = state.transitions[t];
                    if (!stateDictionary.ContainsKey(transition.destinationState))
                    {
                        continue;
                    }
                    Quantum.AnimatorTransition newTransition = new Quantum.AnimatorTransition();
                    newTransition.index                = t;
                    newTransition.name                 = string.Format("{0} to {1}", state.name, transition.destinationState.name);
                    newTransition.duration             = FP.FromFloat_UNSAFE(transition.duration * state.motion.averageDuration);
                    newTransition.hasExitTime          = transition.hasExitTime;
                    newTransition.exitTime             = FP.FromFloat_UNSAFE(transition.exitTime * state.motion.averageDuration);
                    newTransition.offset               = FP.FromFloat_UNSAFE(transition.offset * transition.destinationState.motion.averageDuration);
                    newTransition.destinationStateId   = stateDictionary[transition.destinationState].id;
                    newTransition.destinationStateName = stateDictionary[transition.destinationState].name;
                    newTransition.canTransitionToSelf  = transition.canTransitionToSelf;


                    int conditionCount = transition.conditions.Length;
                    newTransition.conditions = new Quantum.AnimatorCondition[conditionCount];
                    for (int c = 0; c < conditionCount; c++)
                    {
                        UnityEditor.Animations.AnimatorCondition condition = state.transitions[t].conditions[c];

                        if (!parameterDic.ContainsKey(condition.parameter))
                        {
                            continue;
                        }
                        AnimatorControllerParameter parameter    = parameterDic[condition.parameter];
                        Quantum.AnimatorCondition   newCondition = new Quantum.AnimatorCondition();

                        newCondition.variableName = condition.parameter;
                        newCondition.mode         = (Quantum.AnimatorCondition.Modes)condition.mode;

                        switch (parameter.type)
                        {
                        case AnimatorControllerParameterType.Float:
                            newCondition.thresholdFp = FP.FromFloat_UNSAFE(condition.threshold);
                            break;

                        case AnimatorControllerParameterType.Int:
                            newCondition.thresholdInt = Mathf.RoundToInt(condition.threshold);
                            break;
                        }

                        newTransition.conditions[c] = newCondition;
                    }

                    newState.transitions[t] = newTransition;
                }
            }

            //Create Any State
            Quantum.AnimatorState anyState = new Quantum.AnimatorState();
            anyState.name  = "Any State";
            anyState.id    = anyState.name.GetHashCode();
            anyState.isAny = true;//important for this one
            AnimatorStateTransition[] anyStateTransitions = controller.layers[l].stateMachine.anyStateTransitions;
            int anyStateTransitionCount = anyStateTransitions.Length;
            anyState.transitions = new Quantum.AnimatorTransition[anyStateTransitionCount];
            for (int t = 0; t < anyStateTransitionCount; t++)
            {
                AnimatorStateTransition transition = anyStateTransitions[t];
                if (!stateDictionary.ContainsKey(transition.destinationState))
                {
                    continue;
                }
                Quantum.AnimatorTransition newTransition = new Quantum.AnimatorTransition();
                newTransition.index                = t;
                newTransition.name                 = string.Format("Any State to {0}", transition.destinationState.name);
                newTransition.duration             = FP.FromFloat_UNSAFE(transition.duration);
                newTransition.hasExitTime          = transition.hasExitTime;
                newTransition.exitTime             = FP._1;
                newTransition.offset               = FP.FromFloat_UNSAFE(transition.offset * transition.destinationState.motion.averageDuration);
                newTransition.destinationStateId   = stateDictionary[transition.destinationState].id;
                newTransition.destinationStateName = stateDictionary[transition.destinationState].name;
                newTransition.canTransitionToSelf  = transition.canTransitionToSelf;

                int conditionCount = transition.conditions.Length;
                newTransition.conditions = new Quantum.AnimatorCondition[conditionCount];
                for (int c = 0; c < conditionCount; c++)
                {
                    UnityEditor.Animations.AnimatorCondition condition = anyStateTransitions[t].conditions[c];

                    if (!parameterDic.ContainsKey(condition.parameter))
                    {
                        continue;
                    }
                    AnimatorControllerParameter parameter    = parameterDic[condition.parameter];
                    Quantum.AnimatorCondition   newCondition = new Quantum.AnimatorCondition();

                    newCondition.variableName = condition.parameter;
                    newCondition.mode         = (Quantum.AnimatorCondition.Modes)condition.mode;

                    switch (parameter.type)
                    {
                    case AnimatorControllerParameterType.Float:
                        newCondition.thresholdFp = FP.FromFloat_UNSAFE(condition.threshold);
                        break;

                    case AnimatorControllerParameterType.Int:
                        newCondition.thresholdInt = Mathf.RoundToInt(condition.threshold);
                        break;
                    }

                    newTransition.conditions[c] = newCondition;
                }

                anyState.transitions[t] = newTransition;
            }
            newLayer.states[stateCount] = anyState;

            dataAsset.Settings.layers[l] = newLayer;
        }

        EditorUtility.SetDirty(dataAsset);
    }
        private static Motion RemapMotion(Dictionary <QualifiedAnimation, AnimationClip> remapping, List <QualifiedAnimation> qualifiedAnimations, Dictionary <BlendTree, BlendTree> biTreesReferences, ChildMotion copyOfChild)
        {
            switch (copyOfChild.motion)
            {
            case AnimationClip clip:
                return(remapping[qualifiedAnimations.First(animation => animation.Clip == clip)]);

            case BlendTree tree:
                return(biTreesReferences[tree]);

            default:
                return(copyOfChild.motion);
            }
        }
Пример #14
0
    private void RecursionAnalyzeAnimatorStateMachine(AnimatorStateMachine stateMachine, string animationFlolder)
    {
        //遍历states
        for (int i = 0; i < stateMachine.states.Length; i++)
        {
            var animatorState = stateMachine.states[i];
            var motion        = animatorState.state.motion;
            if (motion != null)
            {
                if (motion is BlendTree)
                {
                    BlendTree bt = motion as BlendTree;

                    ChildMotion[] childMotions = new ChildMotion[bt.children.Length];


                    for (int j = 0; j < bt.children.Length; j++)
                    {
                        var childMotion = bt.children[j];
                        var motionClip  = GetAnimationClip(childMotion.motion.name, animationFlolder);

                        if (motionClip == null)
                        {
                            Debug.LogError("没有找到" + motion.name + "的动画控制器");
                        }
                        else
                        {
                            Debug.Log(string.Format("Name:{0}  Motion:{1}", animatorState.state.name, childMotion.motion));   //根据名字找到对应的prefab 然后找出里面的动画文件加载
                            //childMotion.motion = (Motion)motionClip;

                            //var newChildMotion = new ChildMotion() { motion = motionClip, cycleOffset = childMotion.cycleOffset, mirror = childMotion.mirror, directBlendParameter = childMotion.directBlendParameter, position = childMotion.position, threshold = childMotion.threshold, timeScale = childMotion.timeScale };
                            //childMotion = newChildMotion;

                            childMotions[j] = new ChildMotion()
                            {
                                motion = (Motion)motionClip, cycleOffset = childMotion.cycleOffset, mirror = childMotion.mirror, directBlendParameter = childMotion.directBlendParameter, position = childMotion.position, threshold = childMotion.threshold, timeScale = childMotion.timeScale
                            };
                        }
                    }
                    //bt.children = childMotions;
                    BlendTree newBt = new BlendTree()
                    {
                        blendParameter         = bt.blendParameter,
                        blendParameterY        = bt.blendParameterY,
                        blendType              = bt.blendType,
                        hideFlags              = bt.hideFlags,
                        maxThreshold           = bt.maxThreshold,
                        minThreshold           = bt.minThreshold,
                        name                   = bt.name,
                        useAutomaticThresholds = bt.useAutomaticThresholds,
                        children               = childMotions,
                    };
                    animatorState.state.motion = newBt;
                }
                else
                {
                    animatorState.state.motion = null;
                    var motionClip = GetAnimationClip(motion.name, animationFlolder);
                    if (motionClip == null)
                    {
                        Debug.LogError("没有找到" + motion.name + "的动画控制器");
                    }
                    else
                    {
                        animatorState.state.motion = (Motion)motionClip;
                        Debug.Log(string.Format("Name:{0}  Motion:{1}", animatorState.state.name, motion));
                    }
                }
            }
        }
        //遍历substatemachine
        for (int j = 0; j < stateMachine.stateMachines.Length; j++)
        {
            var stateMachines = stateMachine.stateMachines[j];
            RecursionAnalyzeAnimatorStateMachine(stateMachines.stateMachine, animationFlolder);
        }
    }