StateBehaviour.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. using UnityEngine;
  3. namespace Animancer.FSM
  4. {
  5. /// <summary>Base class for <see cref="MonoBehaviour"/> states to be used in a <see cref="StateMachine{TState}"/>.</summary>
  6. /// <remarks>
  7. /// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/fsm/state-types">State Types</see>
  8. /// </remarks>
  9. /// https://kybernetik.com.au/animancer/api/Animancer.FSM/StateBehaviour
  10. ///
  11. [HelpURL(StateExtensions.APIDocumentationURL + nameof(StateBehaviour))]
  12. public abstract class StateBehaviour : MonoBehaviour, IState
  13. {
  14. /************************************************************************************************************************/
  15. /// <summary>[<see cref="IState.CanEnterState"/>]
  16. /// Determines whether the <see cref="StateMachine{TState}"/> can enter this state.
  17. /// Always returns true unless overridden.
  18. /// </summary>
  19. public virtual bool CanEnterState => true;
  20. /// <summary>[<see cref="IState.CanExitState"/>]
  21. /// Determines whether the <see cref="StateMachine{TState}"/> can exit this state.
  22. /// Always returns true unless overridden.
  23. /// </summary>
  24. public virtual bool CanExitState => true;
  25. /************************************************************************************************************************/
  26. /// <summary>[<see cref="IState.OnEnterState"/>]
  27. /// Asserts that this component isn't already enabled, then enables it.
  28. /// </summary>
  29. public virtual void OnEnterState()
  30. {
  31. #if UNITY_ASSERTIONS
  32. if (enabled)
  33. Debug.LogError($"{nameof(StateBehaviour)} was already enabled before {nameof(OnEnterState)}: {this}", this);
  34. #endif
  35. #if UNITY_EDITOR
  36. // Unity doesn't constantly repaint the Inspector if all the components are collapsed.
  37. // So we can simply force it here to ensure that it shows the correct state being enabled.
  38. else
  39. UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
  40. #endif
  41. enabled = true;
  42. }
  43. /************************************************************************************************************************/
  44. /// <summary>[<see cref="IState.OnExitState"/>]
  45. /// Asserts that this component isn't already disabled, then disables it.
  46. /// </summary>
  47. public virtual void OnExitState()
  48. {
  49. if (this == null)
  50. return;
  51. #if UNITY_ASSERTIONS
  52. if (!enabled)
  53. Debug.LogError($"{nameof(StateBehaviour)} was already disabled before {nameof(OnExitState)}: {this}", this);
  54. #endif
  55. enabled = false;
  56. }
  57. /************************************************************************************************************************/
  58. #if UNITY_EDITOR
  59. /// <summary>[Editor-Only] States start disabled and only the current state gets enabled at runtime.</summary>
  60. /// <remarks>Called in Edit Mode whenever this script is loaded or a value is changed in the Inspector.</remarks>
  61. protected virtual void OnValidate()
  62. {
  63. if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
  64. return;
  65. enabled = false;
  66. }
  67. #endif
  68. /************************************************************************************************************************/
  69. }
  70. }