DirectionalCharacter3D.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 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. namespace Animancer.Samples.Sprites
  6. {
  7. /// <summary>A 3D version of the <see cref="DirectionalCharacter"/>.</summary>
  8. ///
  9. /// <remarks>
  10. /// <strong>Sample:</strong>
  11. /// <see href="https://kybernetik.com.au/animancer/docs/samples/sprites/character-3d">
  12. /// Directional Character 3D</see>
  13. /// </remarks>
  14. ///
  15. /// https://kybernetik.com.au/animancer/api/Animancer.Samples.Sprites/DirectionalCharacter3D
  16. ///
  17. [AddComponentMenu(Strings.SamplesMenuPrefix + "Sprites - Directional Character 3D")]
  18. [AnimancerHelpUrl(typeof(DirectionalCharacter3D))]
  19. public class DirectionalCharacter3D : MonoBehaviour
  20. {
  21. /************************************************************************************************************************/
  22. #if UNITY_PHYSICS_3D
  23. /************************************************************************************************************************/
  24. [Header("Physics")]
  25. [SerializeField] private CapsuleCollider _Collider;
  26. [SerializeField] private Rigidbody _Rigidbody;
  27. [SerializeField, MetersPerSecond] private float _WalkSpeed = 1;
  28. [SerializeField, MetersPerSecond] private float _RunSpeed = 2;
  29. [Header("Animations")]
  30. [SerializeField] private DirectionalAnimations3D _Animancer;
  31. [SerializeField] private DirectionalAnimationSet _Idle;
  32. [SerializeField] private DirectionalAnimationSet _Walk;
  33. [SerializeField] private DirectionalAnimationSet _Run;
  34. [SerializeField] private DirectionalAnimationSet _Push;
  35. private Vector3 _Movement;
  36. private bool _IsPushing;
  37. public enum AnimationGroup
  38. {
  39. Other,
  40. Movement,
  41. }
  42. /************************************************************************************************************************/
  43. protected virtual void Update()
  44. {
  45. Vector2 input = SampleInput.WASD;
  46. if (input != Vector2.zero)
  47. {
  48. input = _Animancer.Animations.Snap(input);
  49. // Convert the input to 3D in the XZ plane.
  50. _Movement = new Vector3(input.x, 0, input.y);
  51. // Apply the camera's rotation and set the forward direction.
  52. Transform camera = _Animancer.Camera;
  53. _Movement = camera.TransformDirection(_Movement);
  54. _Movement.y = 0;
  55. _Movement.Normalize();
  56. _Animancer.Forward = _Movement;
  57. Play(GetMovementAnimations(), AnimationGroup.Movement);
  58. }
  59. else
  60. {
  61. _Movement = Vector3.zero;
  62. Play(_Idle, AnimationGroup.Other);
  63. }
  64. }
  65. /************************************************************************************************************************/
  66. private void Play(DirectionalAnimationSet animations, AnimationGroup group)
  67. => _Animancer.SetAnimations(animations, (int)group);
  68. /************************************************************************************************************************/
  69. private DirectionalAnimationSet GetMovementAnimations()
  70. {
  71. if (_IsPushing)
  72. return _Push;
  73. else if (SampleInput.LeftShiftHold)
  74. return _Run;
  75. else
  76. return _Walk;
  77. }
  78. /************************************************************************************************************************/
  79. protected virtual void OnCollisionEnter(Collision collision)
  80. => OnCollision(collision);
  81. protected virtual void OnCollisionStay(Collision collision)
  82. => OnCollision(collision);
  83. private void OnCollision(Collision collision)
  84. {
  85. if (_IsPushing)
  86. return;
  87. int contactCount = collision.contactCount;
  88. for (int i = 0; i < contactCount; i++)
  89. {
  90. ContactPoint contact = collision.GetContact(i);
  91. // If we're moving directly towards an object (or within 30 degrees of it), we are pushing it.
  92. if (Vector3.Angle(contact.normal, _Movement) > 180 - 30)
  93. {
  94. _IsPushing = true;
  95. return;
  96. }
  97. }
  98. }
  99. /************************************************************************************************************************/
  100. protected virtual void FixedUpdate()
  101. {
  102. _IsPushing = false;
  103. // Determine the desired speed based on the current animation.
  104. float speed = _Animancer.Animations == _Run ? _RunSpeed : _WalkSpeed;
  105. #if UNITY_6000_0_OR_NEWER
  106. _Rigidbody.linearVelocity = _Movement * speed;
  107. #else
  108. _Rigidbody.velocity = _Movement * speed;
  109. #endif
  110. }
  111. /************************************************************************************************************************/
  112. #if UNITY_EDITOR
  113. /************************************************************************************************************************/
  114. protected virtual void OnValidate()
  115. {
  116. if (_Animancer != null)
  117. _Animancer.Animations = _Idle;
  118. }
  119. /************************************************************************************************************************/
  120. #endif
  121. /************************************************************************************************************************/
  122. #else
  123. /************************************************************************************************************************/
  124. protected virtual void Awake()
  125. {
  126. SampleReadMe.LogMissingPhysics3DModuleError(this);
  127. }
  128. /************************************************************************************************************************/
  129. #endif
  130. /************************************************************************************************************************/
  131. }
  132. }