Skip to content

Instantly share code, notes, and snippets.

@immrsv
Last active August 30, 2019 08:25
Show Gist options
  • Save immrsv/62601f18fbbb1c6adc3af5e841e973d8 to your computer and use it in GitHub Desktop.
Save immrsv/62601f18fbbb1c6adc3af5e841e973d8 to your computer and use it in GitHub Desktop.
Unity Animator as a scene controller
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Sirenix.OdinInspector;
// Add this to the object that holds the Animator
public class StateMachineEventReceiver : MonoBehaviour
{
[System.Serializable]
public class MapItem {
public string StateName;
[FoldoutGroup("Events")]
public UnityEvent OnStateEnter;
[FoldoutGroup("Events")]
public UnityEvent OnStateUpdate;
[FoldoutGroup("Events")]
public UnityEvent OnStateExit;
}
public Animator Filter;
public List<MapItem> Map;
private void OnEnable() {
StateMachineEventSource.Enter += StateMachineEventSource_OnStateEnter;
StateMachineEventSource.Update += StateMachineEventSource_OnStateUpdate;
StateMachineEventSource.Exit += StateMachineEventSource_OnStateExit;
}
private void OnDisable() {
StateMachineEventSource.Enter -= StateMachineEventSource_OnStateEnter;
StateMachineEventSource.Update -= StateMachineEventSource_OnStateUpdate;
StateMachineEventSource.Exit -= StateMachineEventSource_OnStateExit;
}
private void StateMachineEventSource_OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
if (Filter != null && animator != Filter) return;
foreach (var item in Map) {
if (stateInfo.IsName(item.StateName)) {
item.OnStateEnter.Invoke();
break;
}
}
}
private void StateMachineEventSource_OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
if (Filter != null && animator != Filter) return;
foreach (var item in Map) {
if (stateInfo.IsName(item.StateName)) {
item.OnStateUpdate.Invoke();
break;
}
}
}
private void StateMachineEventSource_OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
if (Filter != null && animator != Filter) return;
foreach (var item in Map) {
if (stateInfo.IsName(item.StateName)) {
item.OnStateExit.Invoke();
break;
}
}
}
}
using UnityEngine;
[System.Serializable]
public delegate void StateMachineStateEvent(Animator animator, AnimatorStateInfo stateInfo, int layerIndex);
// Add this to the 'root' of the Animator Controller (click on the empty space in the Animator window)
public class StateMachineEventSource : StateMachineBehaviour
{
public static event StateMachineStateEvent Enter;
public static event StateMachineStateEvent Update;
public static event StateMachineStateEvent Exit;
// OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
Enter?.Invoke(animator, stateInfo, layerIndex);
}
// OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
Update?.Invoke(animator, stateInfo, layerIndex);
}
// OnStateExit is called when a transition ends and the state machine finishes evaluating this state
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
Exit?.Invoke(animator, stateInfo, layerIndex);
}
}
@immrsv
Copy link
Author

immrsv commented Mar 15, 2019

Odin is only used to display the list of events for Receiver in the Inspector nicely, it's not required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment