版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/akof1314/article/details/80151030
原因
Unity GUI 里的 Button 可以通过更改 Transition 类型为动画来关联动画事件,Toggle 组件也可以,但是这些动画事件不是 Toggle 值变化时的通知事件,所以需要专门的通知动画事件。
解决
简单的脚本来实现,主要是编辑器部分借鉴使用 SelectableEditor 的代码。完整代码如下:
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Toggle))]
[RequireComponent(typeof(Animator))]
public class ToggleAnimatorTrigger : MonoBehaviour
{
private const string kDefaultOnAnimName = "On";
private const string kDefaultOffAnimName = "Off";
[SerializeField]
private string m_OnTrigger = kDefaultOnAnimName;
[SerializeField]
private string m_OffTrigger = kDefaultOffAnimName;
private Animator m_Animator;
private Toggle m_Toggle;
void Awake()
{
m_Animator = GetComponent<Animator>();
m_Toggle = GetComponent<Toggle>();
m_Toggle.onValueChanged.AddListener(OnToggleValueChanged);
}
private void OnToggleValueChanged(bool on)
{
m_Animator.ResetTrigger(m_OnTrigger);
m_Animator.ResetTrigger(m_OffTrigger);
m_Animator.SetTrigger(on ? m_OnTrigger : m_OffTrigger);
}
}
编辑器代码:
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
[CustomEditor(typeof(ToggleAnimatorTrigger))]
public class ToggleAnimatorTriggerEditor : Editor
{
SerializedProperty m_OnTriggerProperty;
SerializedProperty m_OffTriggerProperty;
void OnEnable()
{
m_OnTriggerProperty = serializedObject.FindProperty("m_OnTrigger");
m_OffTriggerProperty = serializedObject.FindProperty("m_OffTrigger");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
var go = (target as ToggleAnimatorTrigger).gameObject;
var animator = go.GetComponent<Animator>();
EditorGUILayout.LabelField("Transition", "Animation");
++EditorGUI.indentLevel;
{
EditorGUILayout.PropertyField(m_OnTriggerProperty);
EditorGUILayout.PropertyField(m_OffTriggerProperty);
if (animator == null || animator.runtimeAnimatorController == null)
{
Rect buttonRect = EditorGUILayout.GetControlRect();
buttonRect.xMin += EditorGUIUtility.labelWidth;
if (GUI.Button(buttonRect, "Auto Generate Animation", EditorStyles.miniButton))
{
var controller = GenerateSelectableAnimatorContoller(m_OnTriggerProperty.stringValue,
m_OffTriggerProperty.stringValue , go);
if (controller != null)
{
if (animator == null)
animator = go.AddComponent<Animator>();
AnimatorController.SetAnimatorController(animator, controller);
}
}
}
}
--EditorGUI.indentLevel;
serializedObject.ApplyModifiedProperties();
}
private static AnimatorController GenerateSelectableAnimatorContoller(string onTrigger, string offTrigger, GameObject target)
{
if (target == null)
return null;
// Where should we create the controller?
var path = GetSaveControllerPath(target);
if (string.IsNullOrEmpty(path))
return null;
// Create controller and hook up transitions.
var controller = AnimatorController.CreateAnimatorControllerAtPath(path);
GenerateTriggerableTransition(onTrigger, controller);
GenerateTriggerableTransition(offTrigger, controller);
AssetDatabase.ImportAsset(path);
return controller;
}
private static string GetSaveControllerPath(GameObject target)
{
var defaultName = target.gameObject.name;
var message = string.Format("Create a new animator for the game object '{0}':", defaultName);
return EditorUtility.SaveFilePanelInProject("New Animation Contoller", defaultName, "controller", message);
}
private static AnimationClip GenerateTriggerableTransition(string name, AnimatorController controller)
{
// Create the clip
var clip = AnimatorController.AllocateAnimatorClip(name);
AssetDatabase.AddObjectToAsset(clip, controller);
// Create a state in the animatior controller for this clip
var state = controller.AddMotion(clip);
// Add a transition property
controller.AddParameter(name, AnimatorControllerParameterType.Trigger);
// Add an any state transition
var stateMachine = controller.layers[0].stateMachine;
var transition = stateMachine.AddAnyStateTransition(state);
transition.AddCondition(AnimatorConditionMode.If, 0, name);
transition.exitTime = 1f;
transition.duration = 0f;
return clip;
}
}
截图如下: