Search Unity

Poor/Wrong documentation of SMB instantiation

Discussion in 'Animation' started by Johannski, Jul 21, 2017.

  1. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    I use a simple StateMachineBehaviour to be able to subscribe to Entering events and exiting events. I noticed that subsribing to the SMB in necessary to be done at every OnEnable, because the SMB seems to be discarded and recreated at every OnDisable/OnEnable. In the documentation it is said to be best practice to get the component on Start (Which I would rather much prefer, way more elegant), but this is just not the case with the current implementation of SMBs.

    Here are the scripts:
    Code (CSharp):
    1. // --------------------------------------------------------------------------------------------------------------------
    2. // <copyright file="StateMachineEvents.cs" company="Supyrb">
    3. //   Copyright (c) 2017 Supyrb. All rights reserved.
    4. // </copyright>
    5. // <author>
    6. //   Johannes Deml
    7. //   send@johannesdeml.com
    8. // </author>
    9. // --------------------------------------------------------------------------------------------------------------------
    10.  
    11. using System.Collections;
    12. using System.Collections.Generic;
    13. using UnityEngine;
    14.  
    15. namespace Supyrb
    16. {
    17.     public class StateMachineEvents : StateMachineBehaviour
    18.     {
    19.         public delegate void StateMachineDelegate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex);
    20.  
    21.         public event StateMachineDelegate OnAnimationStateEnter;
    22.         public event StateMachineDelegate OnAnimationStateExit;
    23.  
    24.         // OnStateEnter is called before OnStateEnter is called on any state inside this state machine
    25.         public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    26.         {
    27.             Debug.Log("State entered");
    28.             if (OnAnimationStateEnter != null)
    29.             {
    30.                 OnAnimationStateEnter(animator, stateInfo, layerIndex);
    31.             }
    32.         }
    33.  
    34.         // OnStateExit is called before OnStateExit is called on any state inside this state machine
    35.         public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    36.         {
    37.             Debug.Log("State exited");
    38.             if (OnAnimationStateExit != null)
    39.             {
    40.                 OnAnimationStateExit(animator, stateInfo, layerIndex);
    41.             }
    42.         }
    43.     }
    44. }
    45.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Supyrb;
    4. using UnityEngine;
    5.  
    6. [RequireComponent(typeof(Animator))]
    7. public class StateMachineSubscriber : MonoBehaviour
    8. {
    9.     private Animator anim;
    10.     private StateMachineEvents stateMachineEvents;
    11.  
    12.     void Awake()
    13.     {
    14.         anim = GetComponent<Animator>();
    15.     }
    16.  
    17.     /// <summary>
    18.     /// The SMB that is subscribed to gets lost after gameobject is disabled
    19.     /// It would be necessary to subscribe at every OnEnable to the new SMB instance
    20.     /// </summary>
    21.     void Start()
    22.     {
    23.         stateMachineEvents = anim.GetBehaviour<StateMachineEvents>();
    24.         stateMachineEvents.OnAnimationStateEnter += OnStateEnter;
    25.     }
    26.  
    27.     private void OnStateEnter(Animator animator, AnimatorStateInfo stateinfo, int layerindex)
    28.     {
    29.         Debug.Log("State enter received!");
    30.     }
    31. }

    And here is a gif of the outcome. Notice that the event is only received once (because the SMB changes at every deactivation).


    The documentation in question is this one: https://unity3d.com/learn/tutorials/modules/beginner/5-pre-order-beta/state-machine-behaviours

    I do understand why the current implementation is like that, but I think it is rather inconsistent. With ScriptableObjects you would not expect that behavior, and with MonoBehaviours you would for sure not expect that behavior.

    @Mecanim-Dev : Are there any plans to sync the behavior to the (at least from my standpoint) more intuitive one?

    Hope this helps others avoid strange bugs :)
     

    Attached Files:

    theANMATOR2b likes this.