为了更方便地为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);}//Showif (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 TypeGUILayout.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、FadeGUILayout.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();//MoveAnimationvar 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、DelayGUILayout.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 CustomGUILayout.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();//FromGUILayout.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();//ToGUILayout.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();//EaseGUILayout.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();//RotateAnimationvar 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、DelayGUILayout.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 CustomGUILayout.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){//FromGUILayout.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();}//ToGUILayout.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 ModeGUILayout.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();//EaseGUILayout.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();//ScaleAnimationvar 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、DelayGUILayout.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 CustomGUILayout.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){//FromGUILayout.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();}//ToGUILayout.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();//EaseGUILayout.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();//FadeAnimationvar 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、DelayGUILayout.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 CustomGUILayout.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){//FromGUILayout.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();}//ToGUILayout.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();//EaseGUILayout.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、OnEndEventEditorGUILayout.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);}//Hideif (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 TypeGUILayout.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、FadeGUILayout.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();//MoveAnimationvar 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、DelayGUILayout.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();//FromGUILayout.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 CustomGUILayout.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();//ToGUILayout.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();//EaseGUILayout.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();//RotateAnimationvar 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、DelayGUILayout.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 CustomGUILayout.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){//FromGUILayout.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();}//ToGUILayout.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 ModeGUILayout.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();//EaseGUILayout.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();//ScaleAnimationvar 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、DelayGUILayout.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 CustomGUILayout.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){//FromGUILayout.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();}//ToGUILayout.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();//EaseGUILayout.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();//FadeAnimationvar 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、DelayGUILayout.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 CustomGUILayout.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){//FromGUILayout.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();}//ToGUILayout.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();//EaseGUILayout.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、OnEndEventEditorGUILayout.PropertyField(onHideBeginEvent);EditorGUILayout.PropertyField(onHideEndEvent);break;default:break;}}serializedObject.ApplyModifiedProperties();}}
}

Unity 编辑器开发实战【Custom Editor】- 为UI视图制作动画编辑器相关推荐

  1. Unity 编辑器开发实战【Editor Window】- BlendShape调试工具

    Skin Mesh Renderer组件编辑器本身包含BlendShape的调试滑动条,但是当数量较多想要重置时较为麻烦,下面介绍的工具添加了这些调试滑动条的同时,增加了一键重置的功能: 代码如下: ...

  2. Unity 编辑器开发实战【Editor Window】- 关于提高Proto通信协议文件生成效率的考虑

    在项目中使用Protobuf作为通信协议时,需要用到protogen.exe程序将.proto文件编译成.cs文件再导入Unity工程中使用: 例如我们创建一个ProtoTest.proto文件: 然 ...

  3. 《Unity虚拟现实开发实战》——第1章,第1.8节小结

    本节书摘来自华章出版社<Unity虚拟现实开发实战>一书中的第1章,第1.8节小结,作者[美] 乔纳森·林诺维斯,更多章节内容可以访问云栖社区"华章计算机"公众号查看. ...

  4. 《Unity虚拟现实开发实战》——第3章,第3.6节虚拟现实设备的运行原理

    本节书摘来自华章出版社<Unity虚拟现实开发实战>一书中的第3章,第3.6节虚拟现实设备的运行原理,作者[美] 乔纳森·林诺维斯,更多章节内容可以访问云栖社区"华章计算机&qu ...

  5. unity应用开发实战案例_Unity开发实战游戏教学案例分享

    进行项目实战是快速入门或提升Unity开发的关键.Asset Store资源商店中,有大量完整项目模板和教学案例,帮助您通过项目实战,让你体会到Unity开发的成就感. 本文我们为大家准备了三款实战游 ...

  6. 移动端H5页面编辑器开发实战--经验技巧篇

    一.前言 在上一篇<原理结构篇>中,主要针对移动端网页进行了分类描述,并介绍了H5编辑器的需求.原理以及框架结构,本文将延续开发实战这一主题,针对策略和开发技巧做进一步的介绍. 二.策略篇 ...

  7. unity应用开发实战案例_Unity3D游戏引擎开发实战从入门到精通

    Unity3D游戏引擎开发实战从入门到精通(坦克大战项目实战.NGUI开发.GameObject) 一.Unity3D游戏引擎开发实战从入门到精通是怎么样的一门课程(介绍) 1.1.Unity3D游戏 ...

  8. 《Unity开发实战》——2.8节用Shuriken制作粒子效果

    本节书摘来自华章社区<Unity开发实战>一书中的第2章,第2.8节用Shuriken制作粒子效果,作者 (爱尔兰)Matt Smith (巴西)Chico Queiroz,更多章节内容可 ...

  9. Unity 编辑器开发实战【Custom Editor】- FSM Editor

    本文介绍如何为FSM有限状态机模块实现一个自定义编辑器面板,FSM的详细代码在上一篇文章中有介绍,链接地址: 在Unity中构建FSM有限状态机 下面是最终效果: 首先,自定义一个编辑器面板,需要用到 ...

最新文章

  1. Halcon_灰度直方图和特征直方图的使用
  2. 【Android 逆向】IDA 工具使用 ( IDA 32 位 / 64 位 版本 | 汇编代码视图 IDA View-A | 字符串窗口 Strings window )
  3. Elasticsearch 存储模型
  4. 【待继续研究】解析信用评分模型的开发流程及检验标准(晕乎乎,看不懂~)
  5. hdu 2553 N皇后问题【dfs】
  6. 薪水增长多少,新机会才值得考虑?
  7. 200行代码实现视频人物实时去除
  8. python中小数_比较python中的小数
  9. 有哪些开源的 Python 库让你相见恨晚?
  10. 类与方法java讲解_Java中方法使用的深入讲解
  11. 时序分析基本概念介绍<input/output delay>
  12. asp.Net下短信猫发送短信中的中文乱码解决
  13. 【推荐】在R中无缝集成Github云端代码托管
  14. 数字电路与逻辑设计 答案(第三版)
  15. 一个在线QQ客服代码分析
  16. while循环结构的用法
  17. h5学习笔记 左右布局
  18. 《幸福来敲门》观后感
  19. Unity绿幕视频后期制作方案探索
  20. SuperMemo POJ - 3580

热门文章

  1. 洛谷P5594-【XR-4】模拟赛(模拟)
  2. beanmapper java_Java今日收获——BeanMapper
  3. 【Go语言实战】—— 时间戳转标准输出格式,标准输出转时间戳,gorm查询标准化时间
  4. uvm 糖果爱好者 subscriber调用parent方法解读
  5. 从零开始搭建 Filecoin 主网挖矿集群
  6. 回溯法解决01背包-非递归算法-效率低
  7. Python代码写一个玫瑰花
  8. java 账本 创建数据库_想用你所学的JAVA与数据库写一个属于自己的账本吗?一起来看看呗!看如何用java项目操作数据库...
  9. 嵌入式系统测试工具——ETest
  10. springboot最核心的三个特有注解