- Home /
Change the order of animation layers in the mecanim.
How to move "ImmediateTransition" layer to the bottom?
Thanks in advance!
As far as I know, you can't as I've tried as well. But you can give it priority by setting the SetLayerWeight(2,1) to a higher level than the others when you need to use it.
I can not do that, because the lower layer, overwrites the upper one.
The upper one only overwrites the lower one if the weight is set higher or equal. If you want the lower layer to override the upper layer set the lower level weight to one and the higher level weight to zero.
Answer by TJHeuvel-net · Jan 26, 2015 at 04:28 PM
@mouurusai's script didnt work anymore, please see an updated version below. The methods where not available anymore, so i use reflection to call them anyway. Absolutely mindblowing this is not standard behaviour.
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
public class AnimatorSwapLayers : EditorWindow
{
private Vector2 _scrollPosition;
[MenuItem("Window/Animator Swap Layers")]
static void Init()
{
AnimatorSwapLayers window = (AnimatorSwapLayers)GetWindow(typeof(AnimatorSwapLayers));
}
void OnSelectionChange()
{
Repaint();
}
void OnGUI()
{
if (Selection.objects.Length > 0 && Selection.objects[0] is AnimatorController)
{
AnimatorController controller = (AnimatorController)Selection.objects[0];
_scrollPosition = GUILayout.BeginScrollView(_scrollPosition);
for (int i = 0; i < controller.layerCount; i++)
{
GUILayout.BeginHorizontal();
GUILayout.Label(controller.GetLayer(i).name);
GUILayout.FlexibleSpace();
if (i > 0)
{
if (GUILayout.Button("↑"))
{
Swap(controller, i, true);
}
}
if (i < controller.layerCount - 1)
{
if (GUILayout.Button("↓"))
{
Swap(controller, i, false);
}
}
GUILayout.EndHorizontal();
GUILayout.Space(10);
}
GUILayout.EndScrollView();
}
else if (Selection.objects.Length > 1)
{
GUILayout.Label("Multy edit not supported");
}
else
{
GUILayout.Label("No controller selected");
}
}
void Swap(AnimatorController controller, int pos, bool moveUp)
{
int newPos = pos + (moveUp ? -1 : 1);
AnimatorControllerLayer newLayer = controller.GetLayer(newPos),
layer = controller.GetLayer(pos);
AnimatorLayerBlendingMode blendingModeT = newLayer.blendingMode;
bool iKPassT = newLayer.iKPass;
AvatarMask layerMaskT = newLayer.avatarMask;
string nameT = newLayer.name;
StateMachine stateMachineT = newLayer.stateMachine;
int syncedIndexT = newLayer.syncedLayerIndex;
callPrivateMethod(controller, "SetLayerBlendingMode", newPos, layer.blendingMode);
callPrivateMethod(controller, "SetLayerIKPass", newPos, layer.iKPass);
callPrivateMethod(controller, "SetLayerMask", newPos, layer.avatarMask);
callPrivateMethod(controller, "SetLayerName", newPos, layer.name);
callPrivateMethod(controller, "SetLayerStateMachine", newPos, layer.stateMachine);
callPrivateMethod(controller, "SetLayerSyncedIndex", newPos, layer.syncedLayerIndex);
callPrivateMethod(controller, "SetLayerBlendingMode", pos, blendingModeT);
callPrivateMethod(controller, "SetLayerIKPass", pos, iKPassT);
callPrivateMethod(controller, "SetLayerMask", pos, layerMaskT);
callPrivateMethod(controller, "SetLayerName", pos, nameT);
callPrivateMethod(controller, "SetLayerStateMachine", pos, stateMachineT);
callPrivateMethod(controller, "SetLayerSyncedIndex", pos, syncedIndexT);
}
private object callPrivateMethod(object obj, string methodname, params object[] args)
{
var method = obj.GetType().GetMethod(methodname, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (method == null)
Debug.LogError("Couldnt find method!");
return method.Invoke(obj, args);
}
}
I dont have an original post, and the script would be much too long for a comment.
Answer by mouurusai · Jun 25, 2013 at 10:11 AM
Seems is work fine, but why, this absolutely obviously the must have function, is not implemented by default?
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
public class AnimatorSwapLayers : EditorWindow
{
private Vector2 _scrollPosition;
[MenuItem("Window/Animator Swap Layers")]
static void Init ()
{
AnimatorSwapLayers window = (AnimatorSwapLayers)GetWindow(typeof(AnimatorSwapLayers));
}
void OnSelectionChange()
{
Repaint();
}
void OnGUI()
{
if(Selection.objects.Length > 0 && Selection.objects[0] is AnimatorController)
{
AnimatorController controller = (AnimatorController)Selection.objects[0];
_scrollPosition = GUILayout.BeginScrollView(_scrollPosition);
for (int i = 0; i < controller.GetLayerCount(); i++)
{
GUILayout.BeginHorizontal();
GUILayout.Label(controller.GetLayerName(i));
GUILayout.FlexibleSpace();
if(i>0)
{
if (GUILayout.Button("↑"))
{
Swap(controller, i, true);
}
}
if (i < controller.GetLayerCount()-1)
{
if (GUILayout.Button("↓"))
{
Swap(controller, i, false);
}
}
GUILayout.EndHorizontal();
GUILayout.Space(10);
}
GUILayout.EndScrollView();
}
else if (Selection.objects.Length > 1)
{
GUILayout.Label("Multy edit not supported");
}
else
{
GUILayout.Label("No controller selected");
}
}
void Swap(AnimatorController controller, int pos, bool moveUp)
{
int newPos = pos + (moveUp ? -1 : 1);
AnimatorLayerBlendingMode blendingModeT = controller.GetLayerBlendingMode(newPos);
bool iKPassT = controller.GetLayerIKPass(newPos);
AvatarMask layerMaskT = controller.GetLayerMask(newPos);
string nameT = controller.GetLayerName(newPos);
StateMachine stateMachineT = controller.GetLayerStateMachine(newPos);
int syncedIndexT = controller.GetLayerSyncedIndex(newPos);
int layerTypeT = controller.GetLayerType(newPos);
controller.SetLayerBlendingMode(newPos, controller.GetLayerBlendingMode(pos));
controller.SetLayerIKPass(newPos, controller.GetLayerIKPass(pos));
controller.SetLayerMask(newPos, controller.GetLayerMask(pos));
controller.SetLayerName(newPos, controller.GetLayerName(pos));
controller.SetLayerStateMachine(newPos, controller.GetLayerStateMachine(pos));
controller.SetLayerSyncedIndex(newPos, controller.GetLayerSyncedIndex(pos));
controller.SetLayerType(newPos, controller.GetLayerType(pos));
controller.SetLayerBlendingMode(pos, blendingModeT);
controller.SetLayerIKPass(pos, iKPassT);
controller.SetLayerMask(pos, layerMaskT);
controller.SetLayerName(pos, nameT);
controller.SetLayerStateMachine(pos, stateMachineT);
controller.SetLayerSyncedIndex(pos, syncedIndexT);
controller.SetLayerType(pos, layerTypeT);
}
}
This no longer works, controller now has a method to return a layer but it has a state machine variable which is read-only.
Your answer
Follow this Question
Related Questions
Animator sometimes become slow motion by itself. 2 Answers
Mecanim Humaoid rotation conversion error 0 Answers
OnStateEnter isn't updating in the correct order with normal update? 0 Answers
Mecanim transition condition can't have both bool and trigger? 0 Answers
Is it possible to change root motion animations to in place? 3 Answers