AttackState.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
  3. using Animancer.Units;
  4. using UnityEngine;
  5. using UnityEngine.Events;
  6. namespace Animancer.Examples.AnimatorControllers.GameKit
  7. {
  8. /// <summary>A <see cref="CharacterState"/> which plays a series of "attack" animations.</summary>
  9. /// <example><see href="https://kybernetik.com.au/animancer/docs/examples/animator-controllers/3d-game-kit/attack">3D Game Kit/Attack</see></example>
  10. /// https://kybernetik.com.au/animancer/api/Animancer.Examples.AnimatorControllers.GameKit/AttackState
  11. ///
  12. [AddComponentMenu(Strings.ExamplesMenuPrefix + "Game Kit - Attack State")]
  13. [HelpURL(Strings.DocsURLs.ExampleAPIDocumentation + nameof(AnimatorControllers) + "." + nameof(GameKit) + "/" + nameof(AttackState))]
  14. public sealed class AttackState : CharacterState
  15. {
  16. /************************************************************************************************************************/
  17. [SerializeField, DegreesPerSecond] private float _TurnSpeed = 400;
  18. [SerializeField] private UnityEvent _SetWeaponOwner;// See the Read Me.
  19. [SerializeField] private UnityEvent _OnStart;// See the Read Me.
  20. [SerializeField] private UnityEvent _OnEnd;// See the Read Me.
  21. [SerializeField] private ClipTransition[] _Animations;
  22. private int _CurrentAnimationIndex = int.MaxValue;
  23. private ClipTransition _CurrentAnimation;
  24. /************************************************************************************************************************/
  25. private void Awake()
  26. {
  27. _SetWeaponOwner.Invoke();
  28. }
  29. /************************************************************************************************************************/
  30. public override bool CanEnterState => Character.Movement.IsGrounded;
  31. /************************************************************************************************************************/
  32. /// <summary>
  33. /// Start at the beginning of the sequence by default, but if the previous attack hasn't faded out yet then
  34. /// perform the next attack instead.
  35. /// </summary>
  36. private void OnEnable()
  37. {
  38. if (_CurrentAnimationIndex >= _Animations.Length - 1 ||
  39. _Animations[_CurrentAnimationIndex].State.Weight == 0)
  40. {
  41. _CurrentAnimationIndex = 0;
  42. }
  43. else
  44. {
  45. _CurrentAnimationIndex++;
  46. }
  47. _CurrentAnimation = _Animations[_CurrentAnimationIndex];
  48. Character.Animancer.Play(_CurrentAnimation);
  49. Character.Parameters.ForwardSpeed = 0;
  50. _OnStart.Invoke();
  51. }
  52. /************************************************************************************************************************/
  53. private void OnDisable()
  54. {
  55. _OnEnd.Invoke();
  56. }
  57. /************************************************************************************************************************/
  58. public override bool FullMovementControl => false;
  59. /************************************************************************************************************************/
  60. private void FixedUpdate()
  61. {
  62. if (Character.CheckMotionState())
  63. return;
  64. Character.Movement.TurnTowards(Character.Parameters.MovementDirection, _TurnSpeed);
  65. }
  66. /************************************************************************************************************************/
  67. // Use the End Event time to determine when this state is alowed to exit.
  68. // We cannot simply have this method return false and set the End Event to call Character.CheckMotionState
  69. // because it uses TrySetState (instead of ForceSetState) which would be prevented if this returned false.
  70. // And we cannot have this method return true because that would allow other actions like jumping in the
  71. // middle of an attack.
  72. public override bool CanExitState
  73. => _CurrentAnimation.State.NormalizedTime >= _CurrentAnimation.State.Events.NormalizedEndTime;
  74. /************************************************************************************************************************/
  75. }
  76. }