Unity实战之制作动画编辑器
作者:CoderZ1010
为了更方便地为UI视图添加动画,将动画的编辑功能封装在了UI View类中,可以通过编辑器快速的为视图编辑动画。本文将通过Unity制作一个动画编辑器,需要的可以参考一下
为了更方便地为UI视图添加动画,将动画的编辑功能封装在了UI View类中,可以通过编辑器快速的为视图编辑动画。动画分为两种类型,一种是Unity中的Animator动画,该类型直接通过一个字符串类型变量记录动画State状态的名称即可,播放时调用Animator类中的Play方法传入该名称。另一种是DoTween动画,支持视图的移动、旋转、缩放、淡入淡出动画的编辑:
首先看一下动画相关的几个类的数据结构:
using System; using UnityEngine; using DG.Tweening; namespace SK.Framework { /// <summary> /// UI移动动画 /// </summary> [Serializable] public class UIMoveAnimation { public enum MoveMode { MoveIn, MoveOut } /// <summary> /// UI移动动画方向 /// </summary> public enum UIMoveAnimationDirection { Left, Right, Top, Bottom, TopLeft, TopRight, MiddleCenter, BottomLeft, BottomRight, } public float duration = 1f; public float delay; public Ease ease = Ease.Linear; public UIMoveAnimationDirection direction = UIMoveAnimationDirection.Left; public bool isCustom; public Vector3 startValue; public Vector3 endValue; public MoveMode moveMode = MoveMode.MoveIn; public Tween Play(RectTransform target, bool instant = false) { Vector3 pos = Vector3.zero; float xOffset = target.rect.width / 2 + target.rect.width * target.pivot.x; float yOffset = target.rect.height / 2 + target.rect.height * target.pivot.y; switch (direction) { case UIMoveAnimationDirection.Left: pos = new Vector3(-xOffset, 0f, 0f); break; case UIMoveAnimationDirection.Right: pos = new Vector3(xOffset, 0f, 0f); break; case UIMoveAnimationDirection.Top: pos = new Vector3(0f, yOffset, 0f); break; case UIMoveAnimationDirection.Bottom: pos = new Vector3(0f, -yOffset, 0f); break; case UIMoveAnimationDirection.TopLeft: pos = new Vector3(-xOffset, yOffset, 0f); break; case UIMoveAnimationDirection.TopRight: pos = new Vector3(xOffset, yOffset, 0f); break; case UIMoveAnimationDirection.MiddleCenter: pos = Vector3.zero; break; case UIMoveAnimationDirection.BottomLeft: pos = new Vector3(-xOffset, -yOffset, 0f); break; case UIMoveAnimationDirection.BottomRight: pos = new Vector3(xOffset, -yOffset, 0f); break; } switch (moveMode) { case MoveMode.MoveIn: target.anchoredPosition3D = isCustom ? startValue : pos; return target.DOAnchorPos3D(endValue, instant ? 0f : duration).SetDelay(instant ? 0f : delay).SetEase(ease); case MoveMode.MoveOut: target.anchoredPosition3D = startValue; return target.DOAnchorPos3D(isCustom ? endValue : pos, instant ? 0f : duration).SetDelay(instant ? 0f : delay).SetEase(ease); default: return null; } } } }
using System; using UnityEngine; using DG.Tweening; namespace SK.Framework { /// <summary> /// UI旋转动画 /// </summary> [Serializable] public class UIRotateAnimation { public float duration = 1f; public float delay; public Ease ease = Ease.Linear; public Vector3 startValue; public Vector3 endValue; public RotateMode rotateMode = RotateMode.Fast; public bool isCustom; public Tween Play(RectTransform target, bool instant = false) { if (isCustom) { target.localRotation = Quaternion.Euler(startValue); } return target.DORotate(endValue, instant ? 0f : duration, rotateMode).SetDelay(instant ? 0f : delay).SetEase(ease); } } }
using System; using UnityEngine; using DG.Tweening; namespace SK.Framework { /// <summary> /// UI缩放动画 /// </summary> [Serializable] public class UIScaleAnimation { public float duration = 1f; public float delay; public Ease ease = Ease.Linear; public Vector3 startValue = Vector3.zero; public Vector3 endValue = Vector3.one; public bool isCustom; public Tween Play(RectTransform target, bool instant = false) { if (isCustom) { target.localScale = startValue; } return target.DOScale(endValue, instant ? 0f : duration).SetDelay(instant ? 0f : delay).SetEase(ease); } } }
using System; using DG.Tweening; using UnityEngine; namespace SK.Framework { /// <summary> /// UI淡入淡出动画 /// </summary> [Serializable] public class UIFadeAnimation { public float duration = 1f; public float delay; public Ease ease = Ease.Linear; public float startValue; public float endValue = 1f; public bool isCustom; public Tween Play(CanvasGroup target, bool instant = false) { if (isCustom) { target.alpha = startValue; } return target.DOFade(endValue, instant ? 0f : duration).SetDelay(instant ? 0f : delay).SetEase(ease); } } }
namespace SK.Framework { /// <summary> /// UI动画类型 /// </summary> public enum UIAnimationType { /// <summary> /// DoTween动画 /// </summary> Tween, /// <summary> /// Animator动画 /// </summary> Animator, } }
using System; using UnityEngine; namespace SK.Framework { /// <summary> /// UI动画 /// </summary> [Serializable] public class UIAnimation { public UIAnimationType animationType = UIAnimationType.Tween; public string stateName; public bool moveToggle; public UIMoveAnimation moveAnimation; public bool rotateToggle; public UIRotateAnimation rotateAnimation; public bool scaleToggle; public UIScaleAnimation scaleAnimation; public bool fadeToggle; public UIFadeAnimation fadeAnimation; public bool HasTweenAnimation { get { return moveToggle || rotateToggle || scaleToggle || fadeToggle; } } public IChain Play(UIView view, bool instant = false, Action callback = null) { switch (animationType) { case UIAnimationType.Tween: if (HasTweenAnimation) { var chain = view.Sequence(); var cc = new ConcurrentChain(); if (moveToggle) cc.Tween(() => moveAnimation.Play(view.RectTransform, instant)); if (rotateToggle) cc.Tween(() => rotateAnimation.Play(view.RectTransform, instant)); if (scaleToggle) cc.Tween(() => scaleAnimation.Play(view.RectTransform, instant)); if (fadeToggle) cc.Tween(() => fadeAnimation.Play(view.CanvasGroup, instant)); chain.Append(cc).Event(() => callback?.Invoke()).Begin(); return chain; } else { callback?.Invoke(); return null; } case UIAnimationType.Animator: return view.Sequence() .Animation(view.GetComponent<Animator>(), stateName) .Event(() => callback?.Invoke()) .Begin(); default: return null; } } } }
在UI View类中的相关变量如下:
using System; using UnityEngine.Events; namespace SK.Framework { [Serializable] public class ViewVisibilityChangedEvent { public UIAnimation animation = new UIAnimation(); public UnityEvent onBeginEvent; public UnityEvent onEndEvent; } }
为UI View创建Custom Editor:
using System; using UnityEngine; using UnityEditor; using DG.Tweening; using System.Reflection; using UnityEditor.Animations; using UnityEditor.AnimatedValues; namespace SK.Framework { [CustomEditor(typeof(UIView), true)] public class UIViewInspector : Editor { private enum Menu { Animation, UnityEvent, } private UIView Target; private SerializedProperty variables; private ViewVisibilityChangedEvent onShow; private ViewVisibilityChangedEvent onHide; private static string uiViewOnShowFoldout = "UIView OnShow Foldout"; private static string uiViewOnHideFoldout = "UIView OnHide Foldout"; private bool onShowFoldout; private bool onHideFoldout; private Menu onShowMenu = Menu.Animation; private Menu onHideMenu = Menu.Animation; private SerializedProperty onShowBeginEvent; private SerializedProperty onShowEndEvent; private SerializedProperty onHideBeginEvent; private SerializedProperty onHideEndEvent; private AnimBool onShowMoveAnimBool; private AnimBool onShowRotateAnimBool; private AnimBool onShowScaleAnimBool; private AnimBool onShowFadeAnimBool; private AnimBool onHideMoveAnimBool; private AnimBool onHideRotateAnimBool; private AnimBool onHideScaleAnimBool; private AnimBool onHideFadeAnimBool; private const float titleWidth = 80f; private const float labelWidth = 60f; public override void OnInspectorGUI() { if (Target == null) { Target = target as UIView; onShow = typeof(UIView).GetField("onVisible", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Target) as ViewVisibilityChangedEvent; onHide = typeof(UIView).GetField("onInvisible", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Target) as ViewVisibilityChangedEvent; variables = serializedObject.FindProperty("variables"); onShowFoldout = EditorPrefs.GetBool(uiViewOnShowFoldout); onHideFoldout = EditorPrefs.GetBool(uiViewOnHideFoldout); onShowBeginEvent = serializedObject.FindProperty("onVisible").FindPropertyRelative("onBeginEvent"); onShowEndEvent = serializedObject.FindProperty("onVisible").FindPropertyRelative("onEndEvent"); onHideBeginEvent = serializedObject.FindProperty("onInvisible").FindPropertyRelative("onBeginEvent"); onHideEndEvent = serializedObject.FindProperty("onInvisible").FindPropertyRelative("onEndEvent"); onShowMoveAnimBool = new AnimBool(onShow.animation.moveToggle, Repaint); onShowRotateAnimBool = new AnimBool(onShow.animation.rotateToggle, Repaint); onShowScaleAnimBool = new AnimBool(onShow.animation.scaleToggle, Repaint); onShowFadeAnimBool = new AnimBool(onShow.animation.fadeToggle, Repaint); onHideMoveAnimBool = new AnimBool(onHide.animation.moveToggle, Repaint); onHideRotateAnimBool = new AnimBool(onHide.animation.rotateToggle, Repaint); onHideScaleAnimBool = new AnimBool(onHide.animation.scaleToggle, Repaint); onHideFadeAnimBool = new AnimBool(onHide.animation.fadeToggle, Repaint); } EditorGUILayout.PropertyField(variables); //On Show 折叠栏 var newOnShowFoldout = EditorGUILayout.Foldout(onShowFoldout, "On Visible", true); if (newOnShowFoldout != onShowFoldout) { onShowFoldout = newOnShowFoldout; EditorPrefs.SetBool(uiViewOnShowFoldout, onShowFoldout); } //Show if (onShowFoldout) { GUILayout.BeginHorizontal(); Color color = GUI.color; GUI.color = onShowMenu == Menu.Animation ? Color.cyan : color; if (GUILayout.Button("Animation", "ButtonLeft")) { onShowMenu = Menu.Animation; } GUI.color = onShowMenu == Menu.UnityEvent ? Color.cyan : color; if (GUILayout.Button("Event", "ButtonRight")) { onShowMenu = Menu.UnityEvent; } GUI.color = color; GUILayout.EndHorizontal(); switch (onShowMenu) { case Menu.Animation: //Animation Type GUILayout.BeginHorizontal(); GUILayout.Label("Mode", GUILayout.Width(titleWidth)); var newOnShowAnimationType = (UIAnimationType)EditorGUILayout.EnumPopup(onShow.animation.animationType); if (newOnShowAnimationType != onShow.animation.animationType) { Undo.RecordObject(Target, "On Show Animation Type"); onShow.animation.animationType = newOnShowAnimationType; EditorUtility.SetDirty(Target); } GUILayout.EndHorizontal(); UIAnimation animation = onShow.animation; switch (animation.animationType) { case UIAnimationType.Tween: //Move、Rotate、Scale、Fade GUILayout.BeginHorizontal(); { GUI.color = animation.moveToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("MoveTool"), "ButtonLeft", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Show Animation Move Toggle"); animation.moveToggle = !animation.moveToggle; onShowMoveAnimBool.target = animation.moveToggle; EditorUtility.SetDirty(Target); } GUI.color = animation.rotateToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("RotateTool"), "ButtonMid", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Show Animation Rotate Toggle"); animation.rotateToggle = !animation.rotateToggle; onShowRotateAnimBool.target = animation.rotateToggle; EditorUtility.SetDirty(Target); } GUI.color = animation.scaleToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("ScaleTool"), "ButtonMid", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Show Animation Scale Toggle"); animation.scaleToggle = !animation.scaleToggle; onShowScaleAnimBool.target = animation.scaleToggle; EditorUtility.SetDirty(Target); } GUI.color = animation.fadeToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("ViewToolOrbit"), "ButtonRight", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Show Animation Fade Toggle"); animation.fadeToggle = !animation.fadeToggle; onShowFadeAnimBool.target = animation.fadeToggle; EditorUtility.SetDirty(Target); } GUI.color = color; } GUILayout.EndHorizontal(); //MoveAnimation var moveAnimation = animation.moveAnimation; if (EditorGUILayout.BeginFadeGroup(onShowMoveAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(40f); GUILayout.Label(EditorGUIUtility.IconContent("MoveTool")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(moveAnimation.duration); if (newDuration != moveAnimation.duration) { Undo.RecordObject(Target, "On Show Animation Move Duration"); moveAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(moveAnimation.delay); if (newDelay != moveAnimation.delay) { Undo.RecordObject(Target, "On Show Animation Move Delay"); moveAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(moveAnimation.isCustom ? "Custom Position" : "Direction", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Direction"), !moveAnimation.isCustom, () => { moveAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Custom Position"), moveAnimation.isCustom, () => { moveAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); //From GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); if (moveAnimation.isCustom) { Vector3 newStartValue = EditorGUILayout.Vector3Field(GUIContent.none, moveAnimation.startValue); if (newStartValue != moveAnimation.startValue) { Undo.RecordObject(Target, "On Show Animation Move From"); moveAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } else { var newMoveDirection = (UIMoveAnimationDirection)EditorGUILayout.EnumPopup(moveAnimation.direction); if (newMoveDirection != moveAnimation.direction) { Undo.RecordObject(Target, "On Show Animation Move Direction"); moveAnimation.direction = newMoveDirection; EditorUtility.SetDirty(Target); } } } GUILayout.EndHorizontal(); //To GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth)); Vector3 newEndValue = EditorGUILayout.Vector3Field(GUIContent.none, moveAnimation.endValue); if (newEndValue != moveAnimation.endValue) { Undo.RecordObject(Target, "On Show Animation Move To"); moveAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(moveAnimation.ease); if (newEase != moveAnimation.ease) { Undo.RecordObject(Target, "On Show Animation Move Ease"); moveAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); //RotateAnimation var rotateAnimation = animation.rotateAnimation; if (EditorGUILayout.BeginFadeGroup(onShowRotateAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(rotateAnimation.isCustom ? 50f : 40f); GUILayout.Label(EditorGUIUtility.IconContent("RotateTool")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(rotateAnimation.duration); if (newDuration != rotateAnimation.duration) { Undo.RecordObject(Target, "On Show Animation Rotate Duration"); rotateAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(rotateAnimation.delay); if (newDelay != rotateAnimation.delay) { Undo.RecordObject(Target, "On Show Animation Rotate Delay"); rotateAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(rotateAnimation.isCustom ? "Fixed Rotation" : "Current Rotation", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Current Rotation"), !rotateAnimation.isCustom, () => { rotateAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Fixed Rotation"), rotateAnimation.isCustom, () => { rotateAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); if (rotateAnimation.isCustom) { //From GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); Vector3 newStartValue = EditorGUILayout.Vector3Field(GUIContent.none, rotateAnimation.startValue); if (newStartValue != rotateAnimation.startValue) { Undo.RecordObject(Target, "On Show Animation Rotate From"); rotateAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } //To GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth)); Vector3 newEndValue = EditorGUILayout.Vector3Field(GUIContent.none, rotateAnimation.endValue); if (newEndValue != rotateAnimation.endValue) { Undo.RecordObject(Target, "On Show Animation Rotate To"); rotateAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Rotate Mode GUILayout.BeginHorizontal(); { GUILayout.Label("Mode", GUILayout.Width(labelWidth)); var newRotateMode = (RotateMode)EditorGUILayout.EnumPopup(rotateAnimation.rotateMode); if (newRotateMode != rotateAnimation.rotateMode) { Undo.RecordObject(Target, "On Show Animation Rotate Mode"); rotateAnimation.rotateMode = newRotateMode; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(rotateAnimation.ease); if (newEase != rotateAnimation.ease) { Undo.RecordObject(Target, "On Show Animation Rotate Ease"); rotateAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); //ScaleAnimation var scaleAnimation = animation.scaleAnimation; if (EditorGUILayout.BeginFadeGroup(onShowScaleAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(scaleAnimation.isCustom ? 40f : 30f); GUILayout.Label(EditorGUIUtility.IconContent("ScaleTool")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(scaleAnimation.duration); if (newDuration != scaleAnimation.duration) { Undo.RecordObject(Target, "On Show Animation Scale Duration"); scaleAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(scaleAnimation.delay); if (newDelay != scaleAnimation.delay) { Undo.RecordObject(Target, "On Show Animation Scale Delay"); scaleAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(scaleAnimation.isCustom ? "Fixed Scale" : "Current Scale", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Current Scale"), !scaleAnimation.isCustom, () => { scaleAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Fixed Scale"), scaleAnimation.isCustom, () => { scaleAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); if (scaleAnimation.isCustom) { //From GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); Vector3 newStartValue = EditorGUILayout.Vector3Field(GUIContent.none, scaleAnimation.startValue); if (newStartValue != scaleAnimation.startValue) { Undo.RecordObject(Target, "On Show Animation Scale From"); scaleAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } //To GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth)); Vector3 newEndValue = EditorGUILayout.Vector3Field(GUIContent.none, scaleAnimation.endValue); if (newEndValue != scaleAnimation.endValue) { Undo.RecordObject(Target, "On Show Animation Scale To"); scaleAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(scaleAnimation.ease); if (newEase != scaleAnimation.ease) { Undo.RecordObject(Target, "On Show Animation Scale Ease"); scaleAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); //FadeAnimation var fadeAnimation = animation.fadeAnimation; if (EditorGUILayout.BeginFadeGroup(onShowFadeAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(fadeAnimation.isCustom ? 40f : 30f); GUILayout.Label(EditorGUIUtility.IconContent("ViewToolOrbit")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(fadeAnimation.duration); if (newDuration != fadeAnimation.duration) { Undo.RecordObject(Target, "On Show Animation Fade Duration"); fadeAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(fadeAnimation.delay); if (newDelay != fadeAnimation.delay) { Undo.RecordObject(Target, "On Show Animation Fade Delay"); fadeAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(fadeAnimation.isCustom ? "Fixed Alpha" : "Current Alpha", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Current Alpha"), !fadeAnimation.isCustom, () => { fadeAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Fixed Alpha"), fadeAnimation.isCustom, () => { fadeAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); if (fadeAnimation.isCustom) { //From GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); float newStartValue = EditorGUILayout.FloatField(GUIContent.none, fadeAnimation.startValue); if (newStartValue != fadeAnimation.startValue) { Undo.RecordObject(Target, "On Show Animation Fade From"); fadeAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } //To GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth)); float newEndValue = EditorGUILayout.FloatField(GUIContent.none, fadeAnimation.endValue); if (newEndValue != fadeAnimation.endValue) { Undo.RecordObject(Target, "On Show Animation Fade To"); fadeAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(fadeAnimation.ease); if (newEase != fadeAnimation.ease) { Undo.RecordObject(Target, "On Show Animation Fade Ease"); fadeAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); break; case UIAnimationType.Animator: var animator = Target.GetComponent<Animator>(); if (animator != null) { var animatorController = animator.runtimeAnimatorController as AnimatorController; var stateMachine = animatorController.layers[0].stateMachine; if (stateMachine.states.Length == 0) { EditorGUILayout.HelpBox("no animator state was found.", MessageType.Info); } else { string[] stateNames = new string[stateMachine.states.Length]; for (int i = 0; i < stateNames.Length; i++) { stateNames[i] = stateMachine.states[i].state.name; } var index = Array.FindIndex(stateNames, m => m == animation.stateName); GUILayout.BeginHorizontal(); GUILayout.Label("State Name", GUILayout.Width(titleWidth)); var newIndex = EditorGUILayout.Popup(index, stateNames); if (newIndex != index) { Undo.RecordObject(Target, "Show Animation State Name"); animation.stateName = stateNames[newIndex]; EditorUtility.SetDirty(Target); } GUILayout.EndHorizontal(); } } else { EditorGUILayout.HelpBox("no animator component on this view.", MessageType.Error); } break; default: break; } break; case Menu.UnityEvent: //OnBeginEvent、OnEndEvent EditorGUILayout.PropertyField(onShowBeginEvent); EditorGUILayout.PropertyField(onShowEndEvent); break; default: break; } } //On Hide 折叠栏 var newOnHideFoldout = EditorGUILayout.Foldout(onHideFoldout, "On Invisible", true); if (newOnHideFoldout != onHideFoldout) { onHideFoldout = newOnHideFoldout; EditorPrefs.SetBool(uiViewOnHideFoldout, onHideFoldout); } //Hide if (onHideFoldout) { GUILayout.BeginHorizontal(); Color color = GUI.color; GUI.color = onHideMenu == Menu.Animation ? Color.cyan : color; if (GUILayout.Button("Animation", "ButtonLeft")) { onHideMenu = Menu.Animation; } GUI.color = onHideMenu == Menu.UnityEvent ? Color.cyan : color; if (GUILayout.Button("Event", "ButtonRight")) { onHideMenu = Menu.UnityEvent; } GUI.color = color; GUILayout.EndHorizontal(); switch (onHideMenu) { case Menu.Animation: //Animation Type GUILayout.BeginHorizontal(); GUILayout.Label("Mode", GUILayout.Width(titleWidth)); var newOnHideAnimationType = (UIAnimationType)EditorGUILayout.EnumPopup(onHide.animation.animationType); if (newOnHideAnimationType != onHide.animation.animationType) { Undo.RecordObject(Target, "On Hide Animation Type"); onHide.animation.animationType = newOnHideAnimationType; } GUILayout.EndHorizontal(); UIAnimation animation = onHide.animation; switch (animation.animationType) { case UIAnimationType.Tween: //Move、Rotate、Scale、Fade GUILayout.BeginHorizontal(); { GUI.color = animation.moveToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("MoveTool"), "ButtonLeft", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Hide Animation Move Toggle"); animation.moveToggle = !animation.moveToggle; onHideMoveAnimBool.target = animation.moveToggle; EditorUtility.SetDirty(Target); } GUI.color = animation.rotateToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("RotateTool"), "ButtonMid", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Hide Animation Rotate Toggle"); animation.rotateToggle = !animation.rotateToggle; onHideRotateAnimBool.target = animation.rotateToggle; EditorUtility.SetDirty(Target); } GUI.color = animation.scaleToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("ScaleTool"), "ButtonMid", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Hide Animation Scale Toggle"); animation.scaleToggle = !animation.scaleToggle; onHideScaleAnimBool.target = animation.scaleToggle; EditorUtility.SetDirty(Target); } GUI.color = animation.fadeToggle ? color : Color.gray; if (GUILayout.Button(EditorGUIUtility.IconContent("ViewToolOrbit"), "ButtonRight", GUILayout.Width(25f))) { Undo.RecordObject(Target, "On Hide Animation Fade Toggle"); animation.fadeToggle = !animation.fadeToggle; onHideFadeAnimBool.target = animation.fadeToggle; EditorUtility.SetDirty(Target); } GUI.color = color; } GUILayout.EndHorizontal(); //MoveAnimation var moveAnimation = animation.moveAnimation; if (EditorGUILayout.BeginFadeGroup(onHideMoveAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(40f); GUILayout.Label(EditorGUIUtility.IconContent("MoveTool")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(moveAnimation.duration); if (newDuration != moveAnimation.duration) { Undo.RecordObject(Target, "On Hide Animation Move Duration"); moveAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(moveAnimation.delay); if (newDelay != moveAnimation.delay) { Undo.RecordObject(Target, "On Hide Animation Move Delay"); moveAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //From GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth)); Vector3 newStartValue = EditorGUILayout.Vector3Field(GUIContent.none, moveAnimation.startValue); if (newStartValue != moveAnimation.startValue) { Undo.RecordObject(Target, "On Hide Animation Move From"); moveAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(moveAnimation.isCustom ? "Custom Position" : "Direction", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Direction"), !moveAnimation.isCustom, () => { moveAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Custom Position"), moveAnimation.isCustom, () => { moveAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); //To GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); if (moveAnimation.isCustom) { Vector3 newEndValue = EditorGUILayout.Vector3Field(GUIContent.none, moveAnimation.endValue); if (newEndValue != moveAnimation.endValue) { Undo.RecordObject(Target, "On Hide Animation Move End"); moveAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } else { var newMoveDirection = (UIMoveAnimationDirection)EditorGUILayout.EnumPopup(moveAnimation.direction); if (newMoveDirection != moveAnimation.direction) { Undo.RecordObject(Target, "On Hide Animation Move Direction"); moveAnimation.direction = newMoveDirection; EditorUtility.SetDirty(Target); } } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(moveAnimation.ease); if (newEase != moveAnimation.ease) { Undo.RecordObject(Target, "On Hide Animation Move Ease"); moveAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); //RotateAnimation var rotateAnimation = animation.rotateAnimation; if (EditorGUILayout.BeginFadeGroup(onHideRotateAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(rotateAnimation.isCustom ? 50f : 40f); GUILayout.Label(EditorGUIUtility.IconContent("RotateTool")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(rotateAnimation.duration); if (newDuration != rotateAnimation.duration) { Undo.RecordObject(Target, "On Hide Animation Rotate Duration"); rotateAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(rotateAnimation.delay); if (newDelay != rotateAnimation.delay) { Undo.RecordObject(Target, "On Hide Animation Rotate Delay"); rotateAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(rotateAnimation.isCustom ? "Fixed Rotation" : "Current Rotation", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Current Rotation"), !rotateAnimation.isCustom, () => { rotateAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Fixed Rotation"), rotateAnimation.isCustom, () => { rotateAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); if (rotateAnimation.isCustom) { //From GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); Vector3 newStartValue = EditorGUILayout.Vector3Field(GUIContent.none, rotateAnimation.startValue); if (newStartValue != rotateAnimation.startValue) { Undo.RecordObject(Target, "On Hide Animation Rotate From"); rotateAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } //To GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth)); Vector3 newEndValue = EditorGUILayout.Vector3Field(GUIContent.none, rotateAnimation.endValue); if (newEndValue != rotateAnimation.endValue) { Undo.RecordObject(Target, "On Hide Animation Rotate To"); rotateAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Rotate Mode GUILayout.BeginHorizontal(); { GUILayout.Label("Mode", GUILayout.Width(labelWidth)); var newRotateMode = (RotateMode)EditorGUILayout.EnumPopup(rotateAnimation.rotateMode); if (newRotateMode != rotateAnimation.rotateMode) { Undo.RecordObject(Target, "On Hide Animation Rotate Mode"); rotateAnimation.rotateMode = newRotateMode; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(rotateAnimation.ease); if (newEase != rotateAnimation.ease) { Undo.RecordObject(Target, "On Hide Animation Rotate Ease"); rotateAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); //ScaleAnimation var scaleAnimation = animation.scaleAnimation; if (EditorGUILayout.BeginFadeGroup(onHideScaleAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(scaleAnimation.isCustom ? 40f : 30f); GUILayout.Label(EditorGUIUtility.IconContent("ScaleTool")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(scaleAnimation.duration); if (newDuration != scaleAnimation.duration) { Undo.RecordObject(Target, "On Hide Animation Scale Duration"); scaleAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(scaleAnimation.delay); if (newDelay != scaleAnimation.delay) { Undo.RecordObject(Target, "On Hide Animation Scale Delay"); scaleAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(scaleAnimation.isCustom ? "Fixed Scale" : "Current Scale", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Current Scale"), !scaleAnimation.isCustom, () => { scaleAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Fixed Scale"), scaleAnimation.isCustom, () => { scaleAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); if (scaleAnimation.isCustom) { //From GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); Vector3 newStartValue = EditorGUILayout.Vector3Field(GUIContent.none, scaleAnimation.startValue); if (newStartValue != scaleAnimation.startValue) { Undo.RecordObject(Target, "On Hide Animation Scale From"); scaleAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } //To GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth)); Vector3 newEndValue = EditorGUILayout.Vector3Field(GUIContent.none, scaleAnimation.endValue); if (newEndValue != scaleAnimation.endValue) { Undo.RecordObject(Target, "On Hide Animation Scale To"); scaleAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(scaleAnimation.ease); if (newEase != scaleAnimation.ease) { Undo.RecordObject(Target, "On Hide Animation Scale Ease"); scaleAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); //FadeAnimation var fadeAnimation = animation.fadeAnimation; if (EditorGUILayout.BeginFadeGroup(onHideFadeAnimBool.faded)) { GUILayout.BeginHorizontal("Badge"); { GUILayout.BeginVertical(); { GUILayout.Space(fadeAnimation.isCustom ? 40f : 30f); GUILayout.Label(EditorGUIUtility.IconContent("ViewToolOrbit")); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { //Duration、Delay GUILayout.BeginHorizontal(); { GUILayout.Label("Duration", GUILayout.Width(labelWidth)); var newDuration = EditorGUILayout.FloatField(fadeAnimation.duration); if (newDuration != fadeAnimation.duration) { Undo.RecordObject(Target, "On Hide Animation Fade Duration"); fadeAnimation.duration = newDuration; EditorUtility.SetDirty(Target); } GUILayout.Label("Delay", GUILayout.Width(labelWidth - 20f)); var newDelay = EditorGUILayout.FloatField(fadeAnimation.delay); if (newDelay != fadeAnimation.delay) { Undo.RecordObject(Target, "On Hide Animation Fade Delay"); fadeAnimation.delay = newDelay; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Is Custom GUILayout.BeginHorizontal(); { GUILayout.Label("From", GUILayout.Width(labelWidth - 2f)); if (GUILayout.Button(fadeAnimation.isCustom ? "Fixed Alpha" : "Current Alpha", "DropDownButton")) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent("Current Alpha"), !fadeAnimation.isCustom, () => { fadeAnimation.isCustom = false; EditorUtility.SetDirty(Target); }); gm.AddItem(new GUIContent("Fixed Alpha"), fadeAnimation.isCustom, () => { fadeAnimation.isCustom = true; EditorUtility.SetDirty(Target); }); gm.ShowAsContext(); } } GUILayout.EndHorizontal(); if (fadeAnimation.isCustom) { //From GUILayout.BeginHorizontal(); { GUILayout.Label(GUIContent.none, GUILayout.Width(labelWidth)); float newStartValue = EditorGUILayout.FloatField(GUIContent.none, fadeAnimation.startValue); if (newStartValue != fadeAnimation.startValue) { Undo.RecordObject(Target, "On Hide Animation Fade From"); fadeAnimation.startValue = newStartValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } //To GUILayout.BeginHorizontal(); { GUILayout.Label("To", GUILayout.Width(labelWidth)); float newEndValue = EditorGUILayout.FloatField(GUIContent.none, fadeAnimation.endValue); if (newEndValue != fadeAnimation.endValue) { Undo.RecordObject(Target, "On Hide Animation Fade To"); fadeAnimation.endValue = newEndValue; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); //Ease GUILayout.BeginHorizontal(); { GUILayout.Label("Ease", GUILayout.Width(labelWidth)); var newEase = (Ease)EditorGUILayout.EnumPopup(fadeAnimation.ease); if (newEase != fadeAnimation.ease) { Undo.RecordObject(Target, "On Hide Animation Fade Ease"); fadeAnimation.ease = newEase; EditorUtility.SetDirty(Target); } } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndFadeGroup(); break; case UIAnimationType.Animator: var animator = Target.GetComponent<Animator>(); if (animator != null) { var animatorController = animator.runtimeAnimatorController as AnimatorController; var stateMachine = animatorController.layers[0].stateMachine; if (stateMachine.states.Length == 0) { EditorGUILayout.HelpBox("no animator state was found.", MessageType.Info); } else { string[] stateNames = new string[stateMachine.states.Length]; for (int i = 0; i < stateNames.Length; i++) { stateNames[i] = stateMachine.states[i].state.name; } var index = Array.FindIndex(stateNames, m => m == animation.stateName); GUILayout.BeginHorizontal(); GUILayout.Label("State Name", GUILayout.Width(titleWidth)); var newIndex = EditorGUILayout.Popup(index, stateNames); if (newIndex != index) { Undo.RecordObject(Target, "Show Animation State Name"); animation.stateName = stateNames[newIndex]; EditorUtility.SetDirty(Target); } GUILayout.EndHorizontal(); } } else { EditorGUILayout.HelpBox("no animator component on this view.", MessageType.Error); } break; default: break; } break; case Menu.UnityEvent: //OnBeginEvent、OnEndEvent EditorGUILayout.PropertyField(onHideBeginEvent); EditorGUILayout.PropertyField(onHideEndEvent); break; default: break; } } serializedObject.ApplyModifiedProperties(); } } }
以上就是Unity实战之制作动画编辑器的详细内容,更多关于Unity动画编辑器的资料请关注脚本之家其它相关文章!