123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
- using Animancer.Units;
- using UnityEngine;
- namespace Animancer.Samples.Sprites
- {
- /// <summary>A 3D version of the <see cref="DirectionalCharacter"/>.</summary>
- ///
- /// <remarks>
- /// <strong>Sample:</strong>
- /// <see href="https://kybernetik.com.au/animancer/docs/samples/sprites/character-3d">
- /// Directional Character 3D</see>
- /// </remarks>
- ///
- /// https://kybernetik.com.au/animancer/api/Animancer.Samples.Sprites/DirectionalCharacter3D
- ///
- [AddComponentMenu(Strings.SamplesMenuPrefix + "Sprites - Directional Character 3D")]
- [AnimancerHelpUrl(typeof(DirectionalCharacter3D))]
- public class DirectionalCharacter3D : MonoBehaviour
- {
- /************************************************************************************************************************/
- #if UNITY_PHYSICS_3D
- /************************************************************************************************************************/
- [Header("Physics")]
- [SerializeField] private CapsuleCollider _Collider;
- [SerializeField] private Rigidbody _Rigidbody;
- [SerializeField, MetersPerSecond] private float _WalkSpeed = 1;
- [SerializeField, MetersPerSecond] private float _RunSpeed = 2;
- [Header("Animations")]
- [SerializeField] private DirectionalAnimations3D _Animancer;
- [SerializeField] private DirectionalAnimationSet _Idle;
- [SerializeField] private DirectionalAnimationSet _Walk;
- [SerializeField] private DirectionalAnimationSet _Run;
- [SerializeField] private DirectionalAnimationSet _Push;
- private Vector3 _Movement;
- private bool _IsPushing;
- public enum AnimationGroup
- {
- Other,
- Movement,
- }
- /************************************************************************************************************************/
- protected virtual void Update()
- {
- Vector2 input = SampleInput.WASD;
- if (input != Vector2.zero)
- {
- input = _Animancer.Animations.Snap(input);
- // Convert the input to 3D in the XZ plane.
- _Movement = new Vector3(input.x, 0, input.y);
- // Apply the camera's rotation and set the forward direction.
- Transform camera = _Animancer.Camera;
- _Movement = camera.TransformDirection(_Movement);
- _Movement.y = 0;
- _Movement.Normalize();
- _Animancer.Forward = _Movement;
- Play(GetMovementAnimations(), AnimationGroup.Movement);
- }
- else
- {
- _Movement = Vector3.zero;
- Play(_Idle, AnimationGroup.Other);
- }
- }
- /************************************************************************************************************************/
- private void Play(DirectionalAnimationSet animations, AnimationGroup group)
- => _Animancer.SetAnimations(animations, (int)group);
- /************************************************************************************************************************/
- private DirectionalAnimationSet GetMovementAnimations()
- {
- if (_IsPushing)
- return _Push;
- else if (SampleInput.LeftShiftHold)
- return _Run;
- else
- return _Walk;
- }
- /************************************************************************************************************************/
- protected virtual void OnCollisionEnter(Collision collision)
- => OnCollision(collision);
- protected virtual void OnCollisionStay(Collision collision)
- => OnCollision(collision);
- private void OnCollision(Collision collision)
- {
- if (_IsPushing)
- return;
- int contactCount = collision.contactCount;
- for (int i = 0; i < contactCount; i++)
- {
- ContactPoint contact = collision.GetContact(i);
- // If we're moving directly towards an object (or within 30 degrees of it), we are pushing it.
- if (Vector3.Angle(contact.normal, _Movement) > 180 - 30)
- {
- _IsPushing = true;
- return;
- }
- }
- }
- /************************************************************************************************************************/
- protected virtual void FixedUpdate()
- {
- _IsPushing = false;
- // Determine the desired speed based on the current animation.
- float speed = _Animancer.Animations == _Run ? _RunSpeed : _WalkSpeed;
- #if UNITY_6000_0_OR_NEWER
- _Rigidbody.linearVelocity = _Movement * speed;
- #else
- _Rigidbody.velocity = _Movement * speed;
- #endif
- }
- /************************************************************************************************************************/
- #if UNITY_EDITOR
- /************************************************************************************************************************/
- protected virtual void OnValidate()
- {
- if (_Animancer != null)
- _Animancer.Animations = _Idle;
- }
- /************************************************************************************************************************/
- #endif
- /************************************************************************************************************************/
- #else
- /************************************************************************************************************************/
- protected virtual void Awake()
- {
- SampleReadMe.LogMissingPhysics3DModuleError(this);
- }
-
- /************************************************************************************************************************/
- #endif
- /************************************************************************************************************************/
- }
- }
|