Skip to content

Instantly share code, notes, and snippets.

@akof1314
Created August 26, 2016 13:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save akof1314/65ca8ffcf64ccdc802730ddade71a8ff to your computer and use it in GitHub Desktop.
Save akof1314/65ca8ffcf64ccdc802730ddade71a8ff to your computer and use it in GitHub Desktop.
Unity Animator 窗口的控制
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEditor.Animations;
using UnityEditor.Graphs;
using UnityEngine;
public class AnimatorControllerToolReflect
{
private Assembly m_Assembly;
private Type m_TypeAnimatorWindow;
private Type m_TypeGraph;
private Type m_TypeGraphGUI;
private EditorWindow m_AnimatorWindow;
private Graph m_StateMachineGraph;
private GraphGUI m_StateMachineGraphGUI;
private PropertyInfo m_ActiveStateMachineInfo;
private MethodInfo m_AddBreadCrumbInfo;
private MethodInfo m_BuildBreadCrumbsFromSMHierarchyInfo;
private FieldInfo m_ScrollPositionInfo;
private FieldInfo m_GraphExtentsInfo;
private FieldInfo m_GraphClientAreaInfo;
private Assembly assembly
{
get
{
if (m_Assembly == null)
{
m_Assembly = Assembly.GetAssembly(typeof(Graph));
}
return m_Assembly;
}
}
private Type animatorWindowType
{
get
{
if (m_TypeAnimatorWindow == null)
{
m_TypeAnimatorWindow = assembly.GetType("UnityEditor.Graphs.AnimatorControllerTool");
}
return m_TypeAnimatorWindow;
}
}
private Type graphType
{
get
{
if (m_TypeGraph == null)
{
m_TypeGraph = assembly.GetType("UnityEditor.Graphs.AnimationStateMachine.Graph");
}
return m_TypeGraph;
}
}
private Type graphGUIType
{
get
{
if (m_TypeGraphGUI == null)
{
m_TypeGraphGUI = assembly.GetType("UnityEditor.Graphs.AnimationStateMachine.GraphGUI");
}
return m_TypeGraphGUI;
}
}
public EditorWindow animatorWindow
{
get
{
if (m_AnimatorWindow == null)
{
FieldInfo toolInfo = animatorWindowType.GetField("tool", BindingFlags.Public | BindingFlags.Static);
m_AnimatorWindow = toolInfo.GetValue(null) as EditorWindow;
}
return m_AnimatorWindow;
}
}
public Graph stateMachineGraph
{
get
{
if (m_StateMachineGraph == null)
{
FieldInfo stateMachineGraphInfo = animatorWindowType.GetField("stateMachineGraph", BindingFlags.Public | BindingFlags.Instance);
m_StateMachineGraph = stateMachineGraphInfo.GetValue(animatorWindow) as Graph;
}
return m_StateMachineGraph;
}
}
public GraphGUI stateMachineGraphGUI
{
get
{
if (m_StateMachineGraphGUI == null)
{
FieldInfo stateMachineGraphGUIInfo = animatorWindowType.GetField("stateMachineGraphGUI", BindingFlags.Public | BindingFlags.Instance);
m_StateMachineGraphGUI = stateMachineGraphGUIInfo.GetValue(animatorWindow) as GraphGUI;
}
return m_StateMachineGraphGUI;
}
}
private PropertyInfo activeStateMachineInfoInfo
{
get
{
if (m_ActiveStateMachineInfo == null)
{
m_ActiveStateMachineInfo = graphType.GetProperty("activeStateMachine", BindingFlags.Instance | BindingFlags.Public);
}
return m_ActiveStateMachineInfo;
}
}
public AnimatorStateMachine activeStateMachine
{
get
{
return activeStateMachineInfoInfo.GetValue(stateMachineGraph, null) as AnimatorStateMachine;
}
}
private MethodInfo addBreadCrumbInfo
{
get
{
if (m_AddBreadCrumbInfo == null)
{
m_AddBreadCrumbInfo = animatorWindowType.GetMethod("AddBreadCrumb", BindingFlags.Instance | BindingFlags.Public);
}
return m_AddBreadCrumbInfo;
}
}
public void AddBreadCrumb(UnityEngine.Object target)
{
addBreadCrumbInfo.Invoke(animatorWindow, new object[] {target});
}
private MethodInfo buildBreadCrumbsFromSMHierarchyInfo
{
get
{
if (m_BuildBreadCrumbsFromSMHierarchyInfo == null)
{
m_BuildBreadCrumbsFromSMHierarchyInfo = animatorWindowType.GetMethod("BuildBreadCrumbsFromSMHierarchy", BindingFlags.Instance | BindingFlags.Public);
}
return m_BuildBreadCrumbsFromSMHierarchyInfo;
}
}
public void BuildBreadCrumbsFromSMHierarchy(IEnumerable<AnimatorStateMachine> hierarchy)
{
buildBreadCrumbsFromSMHierarchyInfo.Invoke(animatorWindow, new object[] { hierarchy });
}
private FieldInfo scrollPositionInfo
{
get
{
if (m_ScrollPositionInfo == null)
{
m_ScrollPositionInfo = graphGUIType.GetField("m_ScrollPosition", BindingFlags.Instance | BindingFlags.NonPublic);
}
return m_ScrollPositionInfo;
}
}
public Vector2 scrollPosition
{
get
{
return (Vector2)scrollPositionInfo.GetValue(stateMachineGraphGUI);
}
set
{
scrollPositionInfo.SetValue(stateMachineGraphGUI, value);
}
}
private FieldInfo graphExtentsInfo
{
get
{
if (m_GraphExtentsInfo == null)
{
m_GraphExtentsInfo = graphType.GetField("graphExtents", BindingFlags.Instance | BindingFlags.NonPublic);
}
return m_GraphExtentsInfo;
}
}
public Rect graphExtents
{
get
{
return (Rect)graphExtentsInfo.GetValue(stateMachineGraph);
}
}
private FieldInfo graphClientAreaInfo
{
get
{
if (m_GraphClientAreaInfo == null)
{
m_GraphClientAreaInfo = graphGUIType.GetField("m_GraphClientArea", BindingFlags.Instance | BindingFlags.NonPublic);
}
return m_GraphClientAreaInfo;
}
}
public Rect graphClientArea
{
get
{
return (Rect)graphClientAreaInfo.GetValue(stateMachineGraphGUI);
}
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.Animations;
using UnityEditor.Graphs;
public static class AnimatorControllerToolUtil
{
private static AnimatorControllerToolReflect animatorControllerToolReflect;
private static void InitReflect()
{
if (animatorControllerToolReflect == null)
{
animatorControllerToolReflect = new AnimatorControllerToolReflect();
}
}
public static void SyncGraphToUnitySelection()
{
InitReflect();
GraphGUI graphGUI = animatorControllerToolReflect.stateMachineGraphGUI;
// 重要,没有这个设置,将会被底层返回
GUIUtility.hotControl = 0;
graphGUI.SyncGraphToUnitySelection();
}
public static void SetActiveStateMachine(AnimatorController animatorController, AnimatorStateMachine animatorStateMachine)
{
InitReflect();
AnimatorStateMachine activeStateMachine = animatorControllerToolReflect.activeStateMachine;
if (animatorStateMachine != activeStateMachine && animatorStateMachine != null)
{
List<AnimatorStateMachine> hierarchy = new List<AnimatorStateMachine>();
AnimatorControllerUtil.MecanimUtilities_StateMachineRelativePath(
AnimatorControllerUtil.AnimatorController_BaseLayerStateMachine(animatorController),
animatorStateMachine, ref hierarchy);
animatorControllerToolReflect.BuildBreadCrumbsFromSMHierarchy(hierarchy);
}
}
public static void ScrollToState(AnimatorStateMachine animatorStateMachine, AnimatorState state)
{
InitReflect();
Vector3 pos = AnimatorControllerUtil.AnimatorStateMachine_GetStatePosition(animatorStateMachine, state);
Rect graphExtents = animatorControllerToolReflect.graphExtents;
Rect graphClientArea = animatorControllerToolReflect.graphClientArea;
Vector2 pos2 = new Vector2(pos.x - graphExtents.x - graphClientArea.width / 2 + 100f,
pos.y - graphExtents.y - graphClientArea.height / 2 + 25f);
animatorControllerToolReflect.scrollPosition = pos2;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor.Animations;
public static class AnimatorControllerUtil
{
#region AnimatorController
/// <summary>
/// 获取动画控制器 Base Layer 层的状态机
/// </summary>
/// <param name="animatorController"></param>
/// <returns></returns>
public static AnimatorStateMachine AnimatorController_BaseLayerStateMachine(AnimatorController animatorController)
{
if (animatorController.layers.Length > 0)
{
return animatorController.layers[0].stateMachine;
}
return null;
}
#endregion
#region AnimatorStateMachine
/// <summary>
/// 动画状态机是否包含指定的动画状态(不递归)
/// </summary>
/// <param name="stateMachines"></param>
/// <param name="state"></param>
/// <returns></returns>
public static bool AnimatorStateMachine_HasState(AnimatorStateMachine stateMachine, AnimatorState state, bool recursive = false)
{
for (int i = 0; i < stateMachine.states.Length; i++)
{
if (stateMachine.states[i].state == state)
{
return true;
}
}
if (recursive)
{
return AnimatorStateMachine_StatesRecursive(stateMachine).Any(s => s.state == state);
}
return false;
}
/// <summary>
/// 获取所有子状态机(递归)
/// </summary>
/// <param name="stateMachines"></param>
/// <returns></returns>
public static List<ChildAnimatorStateMachine> AnimatorStateMachine_StateMachinesRecursive(AnimatorStateMachine stateMachine)
{
List<ChildAnimatorStateMachine> list = new List<ChildAnimatorStateMachine>();
list.AddRange(stateMachine.stateMachines);
for (int i = 0; i < stateMachine.stateMachines.Length; i++)
{
list.AddRange(AnimatorStateMachine_StateMachinesRecursive(stateMachine.stateMachines[i].stateMachine));
}
return list;
}
/// <summary>
/// 获取所有的动画状态(递归)
/// </summary>
/// <param name="stateMachines"></param>
/// <returns></returns>
public static List<ChildAnimatorState> AnimatorStateMachine_StatesRecursive(AnimatorStateMachine stateMachine)
{
List<ChildAnimatorState> list = new List<ChildAnimatorState>();
list.AddRange(stateMachine.states);
for (int i = 0; i < stateMachine.stateMachines.Length; i++)
{
list.AddRange(AnimatorStateMachine_StatesRecursive(stateMachine.stateMachines[i].stateMachine));
}
return list;
}
public static Vector3 AnimatorStateMachine_GetStatePosition(AnimatorStateMachine stateMachine, AnimatorState state)
{
ChildAnimatorState[] states = stateMachine.states;
for (int i = 0; i < states.Length; i++)
{
if (state == states[i].state)
{
return states[i].position;
}
}
return Vector3.zero;
}
#endregion
#region AnimatorState
/// <summary>
/// 查找动画状态的所在状态机
/// </summary>
/// <param name="state"></param>
/// <param name="root"></param>
/// <returns></returns>
public static AnimatorStateMachine AnimatorState_FindParent(AnimatorState state, AnimatorStateMachine root)
{
if (AnimatorStateMachine_HasState(root, state))
{
return root;
}
return AnimatorStateMachine_StateMachinesRecursive(root).Find(machine =>
AnimatorStateMachine_HasState(machine.stateMachine, state)
).stateMachine;
}
#endregion
#region MecanimUtilities
public static bool MecanimUtilities_StateMachineRelativePath(AnimatorStateMachine parent, AnimatorStateMachine toFind, ref List<AnimatorStateMachine> hierarchy)
{
hierarchy.Add(parent);
if (parent == toFind)
{
return true;
}
for (int i = 0; i < parent.stateMachines.Length; i++)
{
if (MecanimUtilities_StateMachineRelativePath(parent.stateMachines[i].stateMachine, toFind, ref hierarchy))
{
return true;
}
}
hierarchy.Remove(parent);
return false;
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment