Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Script to Copy StateMachines/Whole Controllers

Discussion in 'Immediate Mode GUI (IMGUI)' started by mambo_2, Jun 9, 2015.

  1. mambo_2

    mambo_2

    Joined:
    Aug 19, 2013
    Posts:
    19
    Hello,

    Below you can find a script I made to copy state machines with their transitions from one controller to the other, this preserved all the transition exit times, interruption sources, etc... everything I need to use when I wrote it. the code is not clean and a bit clamped so if anyone wants to modify it and make it better by all means.. do so.

    it has not been tested thoroughly and currently it is setup to copy one layer but once you have one layer down it is not too hard to copy the rest.


    a few pointers before using it:

    - modify the clearing script, either to avoid copying or to clear the controller before copying.
    - BlendTrees need testing, I think one of the problem is referencing the same motion from the source.
    - modify to include all layers.
    - if I had the time I would list the states before copying them so I can choose which one I want and which one I do not, maybe even use a node editor inside the window, up to you and how free you are but it's an idea.



    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using UnityEditorInternal;
    4. using System.Collections;
    5. using System.Reflection;
    6.  
    7. public class CopyController : EditorWindow
    8. {
    9.     UnityEditor.Animations.AnimatorController source;
    10.     UnityEditor.Animations.AnimatorController destination;
    11.     UnityEditor.Animations.AnimatorState newState;
    12.     UnityEditor.Animations.AnimatorState destinationState;
    13.     UnityEditor.Animations.AnimatorState defaultState;
    14.     UnityEditor.Animations.AnimatorStateMachine newStateMachine;
    15.     UnityEditor.Animations.AnimatorStateTransition newTransition;
    16.     UnityEditor.Animations.AnimatorTransition newEntryTransition;
    17.  
    18.     Vector3 entryStatePosition;
    19.     bool isExit;
    20.     string defaultStateName;
    21.  
    22.     [MenuItem("Helpers/Copy Controller")]
    23.     static void GetWindow()
    24.     {
    25.         EditorWindow.GetWindow(typeof(CopyController));
    26.     }
    27.  
    28.     void OnGUI()
    29.     {
    30.         source = EditorGUILayout.ObjectField("Source", source, typeof(UnityEditor.Animations.AnimatorController), true, GUILayout.ExpandWidth(true)) as UnityEditor.Animations.AnimatorController;
    31.         destination = EditorGUILayout.ObjectField("Destination", destination, typeof(UnityEditor.Animations.AnimatorController), true, GUILayout.ExpandWidth(true)) as UnityEditor.Animations.AnimatorController;
    32.  
    33.         GUILayout.Space(100);
    34.  
    35.  
    36.         if (GUILayout.Button("Copy", GUILayout.ExpandWidth(true), GUILayout.Height(50)))
    37.         {
    38.             if (source != null && destination != null)
    39.                 Copy();
    40.         }
    41.  
    42.  
    43.         GUILayout.Space(10);
    44.  
    45.         //if (GUILayout.Button("Clear", GUILayout.ExpandWidth(true), GUILayout.Height(50)))
    46.         //{
    47.         //    if (source != null && destination != null)
    48.         //        Clear();
    49.         //}
    50.     }
    51.  
    52.  
    53.     void ClearDestination()
    54.     {
    55.         //Clear Transitions.
    56.         for (int j = 0; j < destination.layers[0].stateMachine.states.Length; j++)
    57.         {
    58.             while (destination.layers[0].stateMachine.states[j].state.transitions.Length != 0)
    59.             {
    60.                 for (int k = 0; k < destination.layers[0].stateMachine.states[j].state.transitions.Length; k++)
    61.                 {
    62.                     destination.layers[0].stateMachine.states[j].state.RemoveTransition(destination.layers[0].stateMachine.states[j].state.transitions[k]);
    63.                 }
    64.             }
    65.         }
    66.  
    67.  
    68.         //Clear Parameters.
    69.         while (destination.layers[0].stateMachine.states.Length != 0)
    70.         {
    71.             for (int j = 0; j < destination.layers[0].stateMachine.states.Length; j++)
    72.             {
    73.                 destination.layers[0].stateMachine.RemoveState(destination.layers[0].stateMachine.states[j].state);
    74.  
    75.             }
    76.         }
    77.  
    78.  
    79.         //Clear States.
    80.         while (destination.parameters.Length > 0)
    81.         {
    82.  
    83.             for (int j = 0; j < destination.parameters.Length; j++)
    84.             {
    85.                 destination.RemoveParameter(destination.parameters[j]);
    86.             }
    87.         }
    88.     }
    89.  
    90.     void Copy()
    91.     {
    92.  
    93.         ClearDestination();
    94.  
    95.  
    96.         //Copy Parameters
    97.         for (int i = 0; i < source.parameters.Length; i++)
    98.         {
    99.             destination.AddParameter(source.parameters[i].name, source.parameters[i].type);
    100.         }
    101.  
    102.         CopyStates(source.layers[0].stateMachine, destination.layers[0].stateMachine, destination.layers[0]);
    103.         CopyTransitions(source.layers[0].stateMachine, destination.layers[0].stateMachine, destination.layers[0]);
    104.         SetDefaultState(source.layers[0].stateMachine, destination.layers[0].stateMachine);
    105.     }
    106.  
    107.  
    108.     void SetDefaultState(UnityEditor.Animations.AnimatorStateMachine stateMachine, UnityEditor.Animations.AnimatorStateMachine destinationStateMachine)
    109.     {
    110.         for(int i = 0; i < destinationStateMachine.states.Length ; i++)
    111.         {
    112.             if (destinationStateMachine.states[i].state.name == stateMachine.defaultState.name)
    113.                 destinationStateMachine.defaultState = destinationStateMachine.states[i].state;
    114.         }
    115.  
    116.         for (int i = 0; i < destinationStateMachine.stateMachines.Length; i++)
    117.         {
    118.             for (int j = 0; j < destinationStateMachine.stateMachines[i].stateMachine.states.Length; j++)
    119.             {
    120.                 if (destinationStateMachine.stateMachines[i].stateMachine.states[j].state.name == stateMachine.defaultState.name)
    121.                     destinationStateMachine.defaultState = destinationStateMachine.stateMachines[i].stateMachine.states[j].state;
    122.             }
    123.         }
    124.     }
    125.  
    126.  
    127.  
    128.     void CopyStates(UnityEditor.Animations.AnimatorStateMachine stateMachine, UnityEditor.Animations.AnimatorStateMachine destinationStateMachine, UnityEditor.Animations.AnimatorControllerLayer destinationLayer)
    129.     {
    130.         destinationStateMachine.exitPosition = stateMachine.exitPosition;
    131.         destinationStateMachine.entryPosition = stateMachine.entryPosition;
    132.         destinationStateMachine.anyStatePosition = stateMachine.anyStatePosition;
    133.  
    134.  
    135.         //Copy States
    136.         for (int i = 0; i < stateMachine.states.Length; i++)
    137.         {
    138.             newState = destinationStateMachine.AddState(stateMachine.states[i].state.name, stateMachine.states[i].position);
    139.             newState.speed = stateMachine.states[i].state.speed;
    140.  
    141.  
    142.  
    143.  
    144.             if (stateMachine.states[i].state.motion != null)
    145.             {
    146.                 if (stateMachine.states[i].state.motion.GetType() == typeof(AnimationClip))
    147.                 {
    148.                     newState.motion = stateMachine.states[i].state.motion;
    149.                 }
    150.                 else
    151.                 {
    152.                     if (stateMachine.states[i].state.motion.GetType() == typeof(UnityEditor.Animations.BlendTree))
    153.                     {
    154.                         UnityEditor.Animations.BlendTree oldBlendTree = stateMachine.states[i].state.motion as UnityEditor.Animations.BlendTree;
    155.                         UnityEditor.Animations.BlendTree newBlendTree = new UnityEditor.Animations.BlendTree();
    156.  
    157.  
    158.                         SerializedObject SO = new SerializedObject(newBlendTree);
    159.                         SerializedProperty SP = SO.GetIterator();
    160.  
    161.                         SP = SO.FindProperty("m_UseAutomaticThresholds");
    162.                         SP.boolValue = false;
    163.                         SO.ApplyModifiedProperties();
    164.  
    165.                         newBlendTree.blendParameter = oldBlendTree.blendParameter;
    166.                         newBlendTree.blendType = oldBlendTree.blendType;
    167.  
    168.                         for (int j = 0; j < oldBlendTree.children.Length; j++)
    169.                         {
    170.                             newBlendTree.AddChild(oldBlendTree.children[j].motion, oldBlendTree.children[j].threshold);
    171.                         }
    172.  
    173.                         for (int j = 0; j < oldBlendTree.children.Length; j++)
    174.                         {
    175.                             UnityEditor.Animations.ChildMotion[] newChildren = newBlendTree.children;
    176.                             newChildren[j].timeScale = oldBlendTree.children[j].timeScale;
    177.                             newChildren[j].position = oldBlendTree.children[j].position;
    178.                             newChildren[j].threshold = oldBlendTree.children[j].threshold;
    179.                             newChildren[j].directBlendParameter = oldBlendTree.children[j].directBlendParameter;
    180.                             newBlendTree.children = newChildren;
    181.                         }
    182.  
    183.                         newState.motion = newBlendTree;
    184.                     }
    185.                 }
    186.             }
    187.         }
    188.  
    189.  
    190.  
    191.         //Set Default State
    192.         for (int i = 0; i < destinationStateMachine.states.Length; i++)
    193.         {
    194.             if (destinationStateMachine.states[i].state.name == defaultStateName)
    195.             {
    196.                 destinationStateMachine.defaultState = destinationStateMachine.states[i].state;
    197.                 break;
    198.             }
    199.         }
    200.  
    201.  
    202.         //Copy Substate Machines
    203.         for (int i = 0; i < stateMachine.stateMachines.Length; i++)
    204.         {
    205.             newStateMachine = new UnityEditor.Animations.AnimatorStateMachine();
    206.             newStateMachine.name = stateMachine.stateMachines[i].stateMachine.name;
    207.             destinationStateMachine.AddStateMachine(newStateMachine.name, stateMachine.stateMachines[i].position);
    208.             CopyStates(stateMachine.stateMachines[i].stateMachine, destinationStateMachine.stateMachines[i].stateMachine, destinationLayer);
    209.         }
    210.  
    211.  
    212.         for (int i = 0; i < stateMachine.stateMachines.Length; i++)
    213.         {
    214.             CopyTransitions(stateMachine.stateMachines[i].stateMachine, destinationStateMachine.stateMachines[i].stateMachine, destinationLayer);
    215.         }
    216.        
    217.     }
    218.  
    219.  
    220.     void CopyTransitions(UnityEditor.Animations.AnimatorStateMachine stateMachine, UnityEditor.Animations.AnimatorStateMachine destinationStateMachine, UnityEditor.Animations.AnimatorControllerLayer destinationLayer)
    221.     {
    222.  
    223.         destinationStateMachine.parentStateMachinePosition = stateMachine.parentStateMachinePosition;
    224.  
    225.  
    226.         //Copy Any Transition
    227.         for (int i = 0; i < stateMachine.anyStateTransitions.Length; i++)
    228.         {
    229.             if (stateMachine.anyStateTransitions[i].destinationState != null)
    230.             {
    231.                 for (int n = 0; n < destinationStateMachine.states.Length; n++)
    232.                 {
    233.                     if (destinationStateMachine.states[n].state.name == stateMachine.anyStateTransitions[i].destinationState.name)
    234.                     {
    235.                         destinationState = destinationStateMachine.states[n].state;
    236.                     }
    237.                 }
    238.  
    239.  
    240.                 newTransition = destinationStateMachine.AddAnyStateTransition(destinationState);
    241.                 newTransition.conditions = stateMachine.anyStateTransitions[i].conditions;
    242.                 newTransition.canTransitionToSelf = stateMachine.anyStateTransitions[i].canTransitionToSelf;
    243.                 newTransition.hasExitTime = stateMachine.anyStateTransitions[i].hasExitTime;
    244.                 newTransition.exitTime = stateMachine.anyStateTransitions[i].exitTime;
    245.                 newTransition.duration = stateMachine.anyStateTransitions[i].duration;
    246.                 newTransition.interruptionSource = stateMachine.anyStateTransitions[i].interruptionSource;
    247.             }
    248.             else
    249.             {
    250.                 for (int n = 0; n < destinationStateMachine.stateMachines.Length; n++)
    251.                 {
    252.                     if (destinationStateMachine.stateMachines[n].stateMachine.name == stateMachine.anyStateTransitions[i].destinationStateMachine.name)
    253.                     {
    254.                         newStateMachine = destinationStateMachine.stateMachines[n].stateMachine;
    255.                     }
    256.                 }
    257.  
    258.                 newTransition = destinationStateMachine.AddAnyStateTransition(newStateMachine);
    259.                 newTransition.conditions = stateMachine.anyStateTransitions[i].conditions;
    260.                 newTransition.canTransitionToSelf = stateMachine.anyStateTransitions[i].canTransitionToSelf;
    261.                 newTransition.hasExitTime = stateMachine.anyStateTransitions[i].hasExitTime;
    262.                 newTransition.exitTime = stateMachine.anyStateTransitions[i].exitTime;
    263.                 newTransition.duration = stateMachine.anyStateTransitions[i].duration;
    264.                 newTransition.interruptionSource = stateMachine.anyStateTransitions[i].interruptionSource;
    265.             }
    266.         }
    267.  
    268.  
    269.         //Copy Entry Transitions
    270.         for (int i = 0; i < stateMachine.entryTransitions.Length; i++)
    271.         {
    272.             if (stateMachine.entryTransitions[i].destinationState != null)
    273.             {
    274.                 for (int n = 0; n < destinationStateMachine.states.Length; n++)
    275.                 {
    276.                     if (destinationStateMachine.states[n].state.name == stateMachine.entryTransitions[i].destinationState.name)
    277.                     {
    278.                         destinationState = destinationStateMachine.states[n].state;
    279.                     }
    280.                 }
    281.  
    282.                 newEntryTransition = destinationStateMachine.AddEntryTransition(destinationState);
    283.                 newEntryTransition.conditions = stateMachine.entryTransitions[i].conditions;
    284.             }
    285.             else
    286.             {
    287.                 for (int n = 0; n < destinationStateMachine.stateMachines.Length; n++)
    288.                 {
    289.                     if (destinationStateMachine.stateMachines[n].stateMachine.name == stateMachine.entryTransitions[i].destinationStateMachine.name)
    290.                     {
    291.                         newStateMachine = destinationStateMachine.stateMachines[n].stateMachine;
    292.                     }
    293.                 }
    294.  
    295.                 newEntryTransition = destinationStateMachine.AddEntryTransition(newStateMachine);
    296.                 newEntryTransition.conditions = stateMachine.anyStateTransitions[i].conditions;
    297.             }
    298.         }
    299.  
    300.  
    301.  
    302.         //Copy State Transitions
    303.         for (int i = 0; i < stateMachine.states.Length; i++)
    304.         {
    305.             for (int j = 0; j < stateMachine.states[i].state.transitions.Length; j++)
    306.             {
    307.                 if (stateMachine.states[i].state.transitions[j].destinationState != null)
    308.                 {
    309.                     for (int n = 0; n < destinationStateMachine.states.Length; n++)
    310.                     {
    311.                         if (destinationStateMachine.states[n].state.name == stateMachine.states[i].state.transitions[j].destinationState.name)
    312.                         {
    313.                             newStateMachine = null;
    314.                             destinationState = destinationStateMachine.states[n].state;
    315.                         }
    316.                     }
    317.  
    318.                     for (int n = 0; n < destinationLayer.stateMachine.states.Length; n++)
    319.                     {
    320.                         if (destinationLayer.stateMachine.states[n].state.name == stateMachine.states[i].state.transitions[j].destinationState.name)
    321.                         {
    322.                             newStateMachine = null;
    323.                             destinationState = destinationLayer.stateMachine.states[n].state;
    324.                         }
    325.                     }
    326.  
    327.  
    328.                     for (int n = 0; n < destinationLayer.stateMachine.stateMachines.Length; n++)
    329.                     {
    330.                         for (int m = 0; m < destinationLayer.stateMachine.stateMachines[n].stateMachine.states.Length; m++)
    331.                         {
    332.                             if (destinationLayer.stateMachine.stateMachines[n].stateMachine.states[m].state.name == stateMachine.states[i].state.transitions[j].destinationState.name)
    333.                             {
    334.                                 newStateMachine = null;
    335.                                 destinationState = destinationLayer.stateMachine.stateMachines[n].stateMachine.states[m].state;
    336.                             }
    337.                         }
    338.                     }
    339.  
    340.  
    341.  
    342.  
    343.                  
    344.                    newTransition = destinationStateMachine.states[i].state.AddTransition(destinationState);
    345.  
    346.                    if (stateMachine.states[i].state.transitions[j].isExit)
    347.                        newTransition.isExit = stateMachine.states[i].state.transitions[j].isExit;
    348.  
    349.                    newTransition.hasExitTime = stateMachine.states[i].state.transitions[j].hasExitTime;
    350.                    newTransition.exitTime = stateMachine.states[i].state.transitions[j].exitTime;
    351.                    newTransition.canTransitionToSelf = stateMachine.states[i].state.transitions[j].canTransitionToSelf;
    352.                    newTransition.conditions = stateMachine.states[i].state.transitions[j].conditions;
    353.                    newTransition.duration = stateMachine.states[i].state.transitions[j].duration;
    354.                    newTransition.interruptionSource = stateMachine.states[i].state.transitions[j].interruptionSource;
    355.                    newTransition.orderedInterruption = stateMachine.states[i].state.transitions[j].orderedInterruption;
    356.  
    357.  
    358.                 }
    359.                 else
    360.                 {
    361.                     for (int n = 0; n < destinationStateMachine.stateMachines.Length; n++)
    362.                     {
    363.                         if (destinationStateMachine.stateMachines[n].stateMachine.name == stateMachine.states[i].state.transitions[j].destinationStateMachine.name)
    364.                         {
    365.                             newStateMachine = destinationStateMachine.stateMachines[n].stateMachine;
    366.                             destinationState = null;
    367.                         }
    368.                     }
    369.  
    370.                     newTransition = destinationStateMachine.states[i].state.AddTransition(newStateMachine);
    371.  
    372.                     if (stateMachine.states[i].state.transitions[j].isExit)
    373.                         newTransition.isExit = stateMachine.states[i].state.transitions[j].isExit;
    374.  
    375.                     newTransition.hasExitTime = stateMachine.states[i].state.transitions[j].hasExitTime;
    376.                     newTransition.canTransitionToSelf = stateMachine.states[i].state.transitions[j].canTransitionToSelf;
    377.                     newTransition.conditions = stateMachine.states[i].state.transitions[j].conditions;
    378.                     newTransition.duration = stateMachine.states[i].state.transitions[j].duration;
    379.                     newTransition.interruptionSource = stateMachine.states[i].state.transitions[j].interruptionSource;
    380.                     newTransition.orderedInterruption = stateMachine.states[i].state.transitions[j].orderedInterruption;
    381.                 }
    382.             }
    383.         }
    384.     }
    385. }
     
  2. Deleted User

    Deleted User

    Guest

    Seems like only a few people need this script and I am one of them!
    Recently I made a lot of animations and then I gave up to edit every setting of the transitions.
    I will try this and blend tree, wish I could solve this.
    Thanks so much for your code! Cheers!
     
  3. Aedous

    Aedous

    Joined:
    Jun 20, 2009
    Posts:
    244
    You're not the only one :D, I've actually been thinking to code something like this as I'm working with a lot of animations and need a way to quickly create a base controller when creating a new character, tweak events on animations, modify positioning of frames basically trying to add functionality to the animation window.

    Thanks a lot for this, gives me a head start on trying to wrap my head around it :p.
     
  4. v2-Ton-Studios

    v2-Ton-Studios

    Joined:
    Jul 18, 2012
    Posts:
    238
    Malbers likes this.
  5. SantiagoIsAFK

    SantiagoIsAFK

    Joined:
    Jan 14, 2016
    Posts:
    3
    Bro, you are the best.


    I improved the script:
    The script dont copy the layer, the script copy the state machine and the parameters. So

    If someone want include all layers use a for cycle in the line that have destination.layers[0] and change the 0 for the i.

    Additionaly, before all copy proccess you have to create the layers (this will create the state machine and the first states) this is necessary to modify, clear and copy.

    Next you copy the layer and finally the script of mambo copy the state machine and the parameters.



    I've created this method for copy layers the create additional layers:
    Code (CSharp):
    1.  
    2. static void CopyLayers(AnimatorController source, AnimatorController destination)
    3. {
    4.  
    5.     destination.layers = new AnimatorControllerLayer[0];
    6.    
    7.     //create additional layers
    8.     for (int i = 0; i < source.layers.Length; i++)
    9.     {
    10.         AnimatorControllerLayer layer = new AnimatorControllerLayer
    11.         {
    12.             name = destination.MakeUniqueLayerName(source.layers[i].name),
    13.             avatarMask = source.layers[i].avatarMask,
    14.             blendingMode = source.layers[i].blendingMode,
    15.             syncedLayerIndex = source.layers[i].syncedLayerIndex,
    16.             iKPass = source.layers[i].iKPass,
    17.             defaultWeight = source.layers[i].defaultWeight,
    18.             syncedLayerAffectsTiming = source.layers[i].syncedLayerAffectsTiming,
    19.             stateMachine = new AnimatorStateMachine()
    20.         };
    21.         layer.stateMachine.name = layer.name;
    22.         layer.stateMachine.hideFlags = HideFlags.HideInHierarchy;
    23.        
    24.         if (AssetDatabase.GetAssetPath((UnityEngine.Object) destination) != "")
    25.             AssetDatabase.AddObjectToAsset((UnityEngine.Object) layer.stateMachine, AssetDatabase.GetAssetPath((UnityEngine.Object) destination));
    26.        
    27.        
    28.         destination.AddLayer(layer);
    29.     }
    30. }
    31.  


    My script is no finish but work for what I need.
    My script is not an editor windows because I use this in other windows, so, if anyone have interest I created un extension method. so, you can duplicate in this way:

    Code (CSharp):
    1. AnimatorController controllerRef;
    2.         AnimatorController controller;
    3.          controllerRef.Clone(controller);

    And the extension class is this (is a variety for the mambo_2's script with layers copy):

    Code (CSharp):
    1. public static AnimatorController Clone(this AnimatorController source, AnimatorController destination)
    2.     {
    3.         // static void Copy(AnimatorController source, AnimatorController destination)
    4.         // {
    5.         CopyLayers(source, destination);
    6.         ClearDestination(destination);
    7.  
    8.         //Copy Parameters
    9.         for (int i = 0; i < source.parameters.Length; i++)
    10.         {
    11.             destination.AddParameter(source.parameters[i].name, source.parameters[i].type);
    12.         }
    13.  
    14.  
    15.         for (int i = 0; i < source.layers.Length; i++)
    16.         {
    17.             CopyStates(source.layers[i].stateMachine, destination.layers[i].stateMachine, destination.layers[i]);
    18.             CopyTransitions(source.layers[i].stateMachine, destination.layers[i].stateMachine, destination.layers[i]);
    19.             SetDefaultState(source.layers[i].stateMachine, destination.layers[i].stateMachine);
    20.         }
    21.  
    22.  
    23.         return destination;
    24.     }
    25.  
    26.  
    27. static void CopyLayers(AnimatorController source, AnimatorController destination)
    28. {
    29.  
    30.     destination.layers = new AnimatorControllerLayer[0];
    31.    
    32.     //create additional layers
    33.     for (int i = 0; i < source.layers.Length; i++)
    34.     {
    35.         AnimatorControllerLayer layer = new AnimatorControllerLayer
    36.         {
    37.             name = destination.MakeUniqueLayerName(source.layers[i].name),
    38.             avatarMask = source.layers[i].avatarMask,
    39.             blendingMode = source.layers[i].blendingMode,
    40.             syncedLayerIndex = source.layers[i].syncedLayerIndex,
    41.             iKPass = source.layers[i].iKPass,
    42.             defaultWeight = source.layers[i].defaultWeight,
    43.             syncedLayerAffectsTiming = source.layers[i].syncedLayerAffectsTiming,
    44.             stateMachine = new AnimatorStateMachine()
    45.         };
    46.         layer.stateMachine.name = layer.name;
    47.         layer.stateMachine.hideFlags = HideFlags.HideInHierarchy;
    48.        
    49.         if (AssetDatabase.GetAssetPath((UnityEngine.Object) destination) != "")
    50.             AssetDatabase.AddObjectToAsset((UnityEngine.Object) layer.stateMachine, AssetDatabase.GetAssetPath((UnityEngine.Object) destination));
    51.        
    52.        
    53.         destination.AddLayer(layer);
    54.     }
    55. }
    56.  
    57.     static void ClearDestination(AnimatorController destination)
    58.     {
    59.         for (int i = 0; i < destination.layers.Length; i++)
    60.         {
    61.             //Clear Transitions.
    62.             for (int j = 0; j < destination.layers[i].stateMachine.states.Length; j++)
    63.             {
    64.                 while (destination.layers[i].stateMachine.states[j].state.transitions.Length != 0)
    65.                 {
    66.                     for (int k = 0; k < destination.layers[i].stateMachine.states[j].state.transitions.Length; k++)
    67.                     {
    68.                         destination.layers[i].stateMachine.states[j].state
    69.                             .RemoveTransition(destination.layers[i].stateMachine.states[j].state.transitions[k]);
    70.                     }
    71.                 }
    72.             }
    73.  
    74.  
    75.             //Clear States.
    76.             while (destination.layers[i].stateMachine.states.Length != 0)
    77.             {
    78.                 for (int j = 0; j < destination.layers[i].stateMachine.states.Length; j++)
    79.                 {
    80.                     destination.layers[i].stateMachine.RemoveState(destination.layers[i].stateMachine.states[j].state);
    81.                 }
    82.             }
    83.  
    84.  
    85.        
    86.         }
    87.    
    88.         //Clear parameters.
    89.         while (destination.parameters.Length > 0)
    90.         {
    91.             for (int j = 0; j < destination.parameters.Length; j++)
    92.             {
    93.                 destination.RemoveParameter(destination.parameters[j]);
    94.             }
    95.         }
    96.     }
    97.  
    98.  
    99.     static void SetDefaultState(UnityEditor.Animations.AnimatorStateMachine stateMachine,
    100.         UnityEditor.Animations.AnimatorStateMachine destinationStateMachine)
    101.     {
    102.         for (int i = 0; i < destinationStateMachine.states.Length; i++)
    103.         {
    104.             if (destinationStateMachine.states[i].state.name == stateMachine.defaultState.name)
    105.                 destinationStateMachine.defaultState = destinationStateMachine.states[i].state;
    106.         }
    107.  
    108.         for (int i = 0; i < destinationStateMachine.stateMachines.Length; i++)
    109.         {
    110.             for (int j = 0; j < destinationStateMachine.stateMachines[i].stateMachine.states.Length; j++)
    111.             {
    112.                 if (destinationStateMachine.stateMachines[i].stateMachine.states[j].state.name ==
    113.                     stateMachine.defaultState.name)
    114.                     destinationStateMachine.defaultState =
    115.                         destinationStateMachine.stateMachines[i].stateMachine.states[j].state;
    116.             }
    117.         }
    118.     }
    119.  
    120.  
    121.     static void CopyStates(UnityEditor.Animations.AnimatorStateMachine stateMachine,
    122.         UnityEditor.Animations.AnimatorStateMachine destinationStateMachine,
    123.         UnityEditor.Animations.AnimatorControllerLayer destinationLayer)
    124.     {
    125.    
    126.         destinationStateMachine.exitPosition = stateMachine.exitPosition;
    127.         destinationStateMachine.entryPosition = stateMachine.entryPosition;
    128.         destinationStateMachine.anyStatePosition = stateMachine.anyStatePosition;
    129.  
    130.         AnimatorState newState;
    131.  
    132.         //Copy States
    133.         for (int i = 0; i < stateMachine.states.Length; i++)
    134.         {
    135.             newState = destinationStateMachine.AddState(stateMachine.states[i].state.name,
    136.                 stateMachine.states[i].position);
    137.             newState.speed = stateMachine.states[i].state.speed;
    138.  
    139.  
    140.             if (stateMachine.states[i].state.motion != null)
    141.             {
    142.                 if (stateMachine.states[i].state.motion.GetType() == typeof(AnimationClip))
    143.                 {
    144.                     newState.motion = stateMachine.states[i].state.motion;
    145.                 }
    146.                 else
    147.                 {
    148.                     if (stateMachine.states[i].state.motion.GetType() == typeof(UnityEditor.Animations.BlendTree))
    149.                     {
    150.                         UnityEditor.Animations.BlendTree oldBlendTree =
    151.                             stateMachine.states[i].state.motion as UnityEditor.Animations.BlendTree;
    152.                         UnityEditor.Animations.BlendTree newBlendTree = new UnityEditor.Animations.BlendTree();
    153.  
    154.  
    155.                         SerializedObject SO = new SerializedObject(newBlendTree);
    156.                         SerializedProperty SP = SO.GetIterator();
    157.  
    158.                         SP = SO.FindProperty("m_UseAutomaticThresholds");
    159.                         SP.boolValue = false;
    160.                         SO.ApplyModifiedProperties();
    161.  
    162.                         newBlendTree.blendParameter = oldBlendTree.blendParameter;
    163.                         newBlendTree.blendType = oldBlendTree.blendType;
    164.  
    165.                         for (int j = 0; j < oldBlendTree.children.Length; j++)
    166.                         {
    167.                             newBlendTree.AddChild(oldBlendTree.children[j].motion,
    168.                                 oldBlendTree.children[j].threshold);
    169.                         }
    170.  
    171.                         for (int j = 0; j < oldBlendTree.children.Length; j++)
    172.                         {
    173.                             UnityEditor.Animations.ChildMotion[] newChildren = newBlendTree.children;
    174.                             newChildren[j].timeScale = oldBlendTree.children[j].timeScale;
    175.                             newChildren[j].position = oldBlendTree.children[j].position;
    176.                             newChildren[j].threshold = oldBlendTree.children[j].threshold;
    177.                             newChildren[j].directBlendParameter = oldBlendTree.children[j].directBlendParameter;
    178.                             newBlendTree.children = newChildren;
    179.                         }
    180.  
    181.                         newState.motion = newBlendTree;
    182.                     }
    183.                 }
    184.             }
    185.         }
    186.  
    187.         string defaultStateName = stateMachine.defaultState.name;
    188.         //Set Default State
    189.         for (int i = 0; i < destinationStateMachine.states.Length; i++)
    190.         {
    191.             if (destinationStateMachine.states[i].state.name == defaultStateName)
    192.             {
    193.                 destinationStateMachine.defaultState = destinationStateMachine.states[i].state;
    194.                 break;
    195.             }
    196.         }
    197.  
    198.         AnimatorStateMachine newStateMachine;
    199.         //Copy Substate Machines
    200.         for (int i = 0; i < stateMachine.stateMachines.Length; i++)
    201.         {
    202.             newStateMachine = new UnityEditor.Animations.AnimatorStateMachine();
    203.             newStateMachine.name = stateMachine.stateMachines[i].stateMachine.name;
    204.             destinationStateMachine.AddStateMachine(newStateMachine.name, stateMachine.stateMachines[i].position);
    205.             CopyStates(stateMachine.stateMachines[i].stateMachine,
    206.                 destinationStateMachine.stateMachines[i].stateMachine, destinationLayer);
    207.         }
    208.  
    209.  
    210.         for (int i = 0; i < stateMachine.stateMachines.Length; i++)
    211.         {
    212.             CopyTransitions(stateMachine.stateMachines[i].stateMachine,
    213.                 destinationStateMachine.stateMachines[i].stateMachine, destinationLayer);
    214.         }
    215.     }
    216.  
    217.  
    218.     static void CopyTransitions(UnityEditor.Animations.AnimatorStateMachine stateMachine,
    219.         UnityEditor.Animations.AnimatorStateMachine destinationStateMachine,
    220.         UnityEditor.Animations.AnimatorControllerLayer destinationLayer)
    221.     {
    222.         destinationStateMachine.parentStateMachinePosition = stateMachine.parentStateMachinePosition;
    223.    
    224.  
    225.         AnimatorState destinationState = new AnimatorState();
    226.         AnimatorStateTransition newTransition;
    227.         AnimatorStateMachine newStateMachine = new AnimatorStateMachine();
    228.         AnimatorTransition newEntryTransition;
    229.  
    230.         //Copy Any Transition
    231.         for (int i = 0; i < stateMachine.anyStateTransitions.Length; i++)
    232.         {
    233.             if (stateMachine.anyStateTransitions[i].destinationState != null)
    234.             {
    235.                 for (int n = 0; n < destinationStateMachine.states.Length; n++)
    236.                 {
    237.                     if (destinationStateMachine.states[n].state.name ==
    238.                         stateMachine.anyStateTransitions[i].destinationState.name)
    239.                     {
    240.                         destinationState = destinationStateMachine.states[n].state;
    241.                     }
    242.                 }
    243.  
    244.  
    245.                 newTransition = destinationStateMachine.AddAnyStateTransition(destinationState);
    246.                 newTransition.conditions = stateMachine.anyStateTransitions[i].conditions;
    247.                 newTransition.canTransitionToSelf = stateMachine.anyStateTransitions[i].canTransitionToSelf;
    248.                 newTransition.hasExitTime = stateMachine.anyStateTransitions[i].hasExitTime;
    249.                 newTransition.exitTime = stateMachine.anyStateTransitions[i].exitTime;
    250.                 newTransition.duration = stateMachine.anyStateTransitions[i].duration;
    251.                 newTransition.interruptionSource = stateMachine.anyStateTransitions[i].interruptionSource;
    252.             }
    253.             else
    254.             {
    255.                 for (int n = 0; n < destinationStateMachine.stateMachines.Length; n++)
    256.                 {
    257.                     if (destinationStateMachine.stateMachines[n].stateMachine.name ==
    258.                         stateMachine.anyStateTransitions[i].destinationStateMachine.name)
    259.                     {
    260.                         newStateMachine = destinationStateMachine.stateMachines[n].stateMachine;
    261.                     }
    262.                 }
    263.  
    264.                 newTransition = destinationStateMachine.AddAnyStateTransition(newStateMachine);
    265.                 newTransition.conditions = stateMachine.anyStateTransitions[i].conditions;
    266.                 newTransition.canTransitionToSelf = stateMachine.anyStateTransitions[i].canTransitionToSelf;
    267.                 newTransition.hasExitTime = stateMachine.anyStateTransitions[i].hasExitTime;
    268.                 newTransition.exitTime = stateMachine.anyStateTransitions[i].exitTime;
    269.                 newTransition.duration = stateMachine.anyStateTransitions[i].duration;
    270.                 newTransition.interruptionSource = stateMachine.anyStateTransitions[i].interruptionSource;
    271.             }
    272.         }
    273.  
    274.  
    275.         //Copy Entry Transitions
    276.         for (int i = 0; i < stateMachine.entryTransitions.Length; i++)
    277.         {
    278.             if (stateMachine.entryTransitions[i].destinationState != null)
    279.             {
    280.                 for (int n = 0; n < destinationStateMachine.states.Length; n++)
    281.                 {
    282.                     if (destinationStateMachine.states[n].state.name ==
    283.                         stateMachine.entryTransitions[i].destinationState.name)
    284.                     {
    285.                         destinationState = destinationStateMachine.states[n].state;
    286.                     }
    287.                 }
    288.  
    289.                 newEntryTransition = destinationStateMachine.AddEntryTransition(destinationState);
    290.                 newEntryTransition.conditions = stateMachine.entryTransitions[i].conditions;
    291.             }
    292.             else
    293.             {
    294.                 for (int n = 0; n < destinationStateMachine.stateMachines.Length; n++)
    295.                 {
    296.                     if (destinationStateMachine.stateMachines[n].stateMachine.name ==
    297.                         stateMachine.entryTransitions[i].destinationStateMachine.name)
    298.                     {
    299.                         newStateMachine = destinationStateMachine.stateMachines[n].stateMachine;
    300.                     }
    301.                 }
    302.  
    303.                 newEntryTransition = destinationStateMachine.AddEntryTransition(newStateMachine);
    304.                 newEntryTransition.conditions = stateMachine.anyStateTransitions[i].conditions;
    305.             }
    306.         }
    307.  
    308.  
    309.         //Copy State Transitions
    310.         for (int i = 0; i < stateMachine.states.Length; i++)
    311.         {
    312.             for (int j = 0; j < stateMachine.states[i].state.transitions.Length; j++)
    313.             {
    314.                 if (stateMachine.states[i].state.transitions[j].destinationState != null)
    315.                 {
    316.                     for (int n = 0; n < destinationStateMachine.states.Length; n++)
    317.                     {
    318.                         if (destinationStateMachine.states[n].state.name ==
    319.                             stateMachine.states[i].state.transitions[j].destinationState.name)
    320.                         {
    321.                             newStateMachine = null;
    322.                             destinationState = destinationStateMachine.states[n].state;
    323.                         }
    324.                     }
    325.  
    326.                     for (int n = 0; n < destinationLayer.stateMachine.states.Length; n++)
    327.                     {
    328.                         if (destinationLayer.stateMachine.states[n].state.name ==
    329.                             stateMachine.states[i].state.transitions[j].destinationState.name)
    330.                         {
    331.                             newStateMachine = null;
    332.                             destinationState = destinationLayer.stateMachine.states[n].state;
    333.                         }
    334.                     }
    335.  
    336.  
    337.                     for (int n = 0; n < destinationLayer.stateMachine.stateMachines.Length; n++)
    338.                     {
    339.                         for (int m = 0;
    340.                              m < destinationLayer.stateMachine.stateMachines[n].stateMachine.states.Length;
    341.                              m++)
    342.                         {
    343.                             if (destinationLayer.stateMachine.stateMachines[n].stateMachine.states[m].state.name ==
    344.                                 stateMachine.states[i].state.transitions[j].destinationState.name)
    345.                             {
    346.                                 newStateMachine = null;
    347.                                 destinationState = destinationLayer.stateMachine.stateMachines[n].stateMachine
    348.                                     .states[m].state;
    349.                             }
    350.                         }
    351.                     }
    352.  
    353.  
    354.                     newTransition = destinationStateMachine.states[i].state.AddTransition(destinationState);
    355.  
    356.                     if (stateMachine.states[i].state.transitions[j].isExit)
    357.                         newTransition.isExit = stateMachine.states[i].state.transitions[j].isExit;
    358.  
    359.                     newTransition.hasExitTime = stateMachine.states[i].state.transitions[j].hasExitTime;
    360.                     newTransition.exitTime = stateMachine.states[i].state.transitions[j].exitTime;
    361.                     newTransition.canTransitionToSelf =
    362.                         stateMachine.states[i].state.transitions[j].canTransitionToSelf;
    363.                     newTransition.conditions = stateMachine.states[i].state.transitions[j].conditions;
    364.                     newTransition.duration = stateMachine.states[i].state.transitions[j].duration;
    365.                     newTransition.interruptionSource =
    366.                         stateMachine.states[i].state.transitions[j].interruptionSource;
    367.                     newTransition.orderedInterruption =
    368.                         stateMachine.states[i].state.transitions[j].orderedInterruption;
    369.                 }
    370.                 else
    371.                 {
    372.                     for (int n = 0; n < destinationStateMachine.stateMachines.Length; n++)
    373.                     {
    374.                         if (destinationStateMachine.stateMachines[n].stateMachine.name == stateMachine.states[i]
    375.                                 .state.transitions[j].destinationStateMachine.name)
    376.                         {
    377.                             newStateMachine = destinationStateMachine.stateMachines[n].stateMachine;
    378.                             destinationState = null;
    379.                         }
    380.                     }
    381.  
    382.                     newTransition = destinationStateMachine.states[i].state.AddTransition(newStateMachine);
    383.  
    384.                     if (stateMachine.states[i].state.transitions[j].isExit)
    385.                         newTransition.isExit = stateMachine.states[i].state.transitions[j].isExit;
    386.  
    387.                     newTransition.hasExitTime = stateMachine.states[i].state.transitions[j].hasExitTime;
    388.                     newTransition.canTransitionToSelf =
    389.                         stateMachine.states[i].state.transitions[j].canTransitionToSelf;
    390.                     newTransition.conditions = stateMachine.states[i].state.transitions[j].conditions;
    391.                     newTransition.duration = stateMachine.states[i].state.transitions[j].duration;
    392.                     newTransition.interruptionSource =
    393.                         stateMachine.states[i].state.transitions[j].interruptionSource;
    394.                     newTransition.orderedInterruption =
    395.                         stateMachine.states[i].state.transitions[j].orderedInterruption;
    396.                 }
    397.             }
    398.         }
    399.     }
     
    Last edited: Feb 15, 2024