Inconsistent StateMachineBehaviour Cloning

Greetings,

I’m finding myself very frustrated with mecanim in 2018.4. I have an “event source” behaviour that listens for OnStateTYPE events, and then converts them to C# events to be picked up by an “event receiver” monobehaviour. This is my workaround to allow scene-object binding into the FSM.

(code includes attributes from Sirenix.OdinInspector)

public delegate void StateMachineStateEvent(Animator animator, AnimatorStateInfo stateInfo, int layerIndex);

[SharedBetweenAnimators]
public class StateMachineStateEventSource : 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) {
        base.OnStateEnter(animator, stateInfo, 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) {
        base.OnStateUpdate(animator, stateInfo, 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) {
        base.OnStateExit(animator, stateInfo, layerIndex);
        Exit?.Invoke(animator, stateInfo, layerIndex);
    }
}
public class StateMachineEventReceiver : MonoBehaviour
{

    [System.Serializable]
    public class MapItem {
        [HideLabel, Tooltip("State/Machine Name or Tag")]
        public string StateId;

        [FoldoutGroup("Enter")]
        public UnityEvent OnStateEnter;
        [FoldoutGroup("Update")]
        public UnityEvent OnStateUpdate;
        [FoldoutGroup("Exit")]
        public UnityEvent OnStateExit;
    }

    public Animator Filter;
    public List<MapItem> Map;

    private void OnEnable() {
        StateMachineStateEventSource.Enter += StateMachineEventSource_OnStateEnter;
        StateMachineStateEventSource.Update += StateMachineEventSource_OnStateUpdate;
        StateMachineStateEventSource.Exit += StateMachineEventSource_OnStateExit;
    }


    private void OnDisable() {
        StateMachineStateEventSource.Enter -= StateMachineEventSource_OnStateEnter;
        StateMachineStateEventSource.Update -= StateMachineEventSource_OnStateUpdate;
        StateMachineStateEventSource.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.StateId) || stateInfo.IsTag(item.StateId) || stateInfo.shortNameHash == Animator.StringToHash(item.StateId)) {
                item.OnStateEnter.Invoke();
                break;
            }
        }
    }
// ....
}

To my delight, I discovered that I could add a behaviour to the top-level StateMachine and it would be automatically added to all States under that machine.

However, I have recently started to use SubstateMachines. Only to find that:

  • The behaviour scripts from the top-level SM are cloned/attached to states inside a SubstateMachine
  • The behaviour scripts from the top-level SM are not cloned/attached to the SubstateMachine nodes
  • Any behaviours added to the SubstateMachine nodes are cloned/attached to internal states

Now, all I want to do is raise an event for entering the SubstateMachine (I’m using the Enter/Exit nodes), but I obviously do not want to raise duplicated enter/exit events for internal states.

Please advise on a means of making this happen, or please consider this a feature/issue request.

1 Like

Well stumbled this post and the same thing happens in Unity 2022.3.10f1