StateBehaviour.cs 3.6 KB

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