// Animancer // Copyright 2020 Kybernetik // #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value. using UnityEngine; namespace Animancer.Examples.StateMachines.Brains { /// /// A which moves the creature according to their /// . /// [AddComponentMenu(Strings.MenuPrefix + "Examples/Brains - Locomotion State")] [HelpURL(Strings.APIDocumentationURL + ".Examples.StateMachines.Brains/LocomotionState")] public sealed class LocomotionState : CreatureState { /************************************************************************************************************************/ [SerializeField] private AnimationClip _Walk; [SerializeField] private AnimationClip _Run; /************************************************************************************************************************/ private void Update() { UpdateAnimation(); UpdateTurning(); } /************************************************************************************************************************/ /// /// This method is similar to the "PlayMove" method in , but instead /// of checking to determine whether or not to run we are checking if the /// says it wants to run. /// private void UpdateAnimation() { // We will play either the Walk or Run animation. // We need to know which animation we are trying to play and which is the other one. AnimationClip playAnimation, otherAnimation; if (Creature.Brain.IsRunning) { playAnimation = _Run; otherAnimation = _Walk; } else { playAnimation = _Walk; otherAnimation = _Run; } // Play the one we want. var playState = Creature.Animancer.Play(playAnimation, 0.25f); // If the brain wants to move slowly, slow down the animation. var speed = Mathf.Min(Creature.Brain.MovementDirection.magnitude, 1); playState.Speed = speed; // If the other one is still fading out, align their NormalizedTime to ensure they stay at the same // relative progress through their walk cycle. var otherState = Creature.Animancer.States[otherAnimation]; if (otherState != null && otherState.IsPlaying) { playState.NormalizedTime = otherState.NormalizedTime; otherState.Speed = speed; } } /************************************************************************************************************************/ private void UpdateTurning() { // Do not turn if we are not trying to move. var movement = Creature.Brain.MovementDirection; if (movement == Vector3.zero) return; // Determine the angle we want to turn towards. // Without going into the maths behind it, Atan2 gives us the angle of a vector in radians. // So we just feed in the x and z values because we want an angle around the y axis, // then convert the result to degrees because Transform.eulerAngles uses degrees. var targetAngle = Mathf.Atan2(movement.x, movement.z) * Mathf.Rad2Deg; // Determine how far we can turn this frame (in degrees). var turnDelta = Creature.Stats.TurnSpeed * Time.deltaTime; // Get the current rotation, move its y value towards the target, and apply it back to the Transform. var transform = Creature.Animancer.transform; var eulerAngles = transform.eulerAngles; eulerAngles.y = Mathf.MoveTowardsAngle(eulerAngles.y, targetAngle, turnDelta); transform.eulerAngles = eulerAngles; } /************************************************************************************************************************/ /// /// Constantly moves the creature according to the . /// /// /// This method is kept simple for the sake of demonstrating the animation system in this example. /// In a real game you would usually not set the velocity directly, but would instead use /// to avoid interfering with collisions and other forces. /// private void FixedUpdate() { // Get the desired direction, remove any vertical component, and limit the magnitude to 1 or less. // Otherwise a brain could make the creature travel at any speed by setting a longer vector. var direction = Creature.Brain.MovementDirection; direction.y = 0; direction = Vector3.ClampMagnitude(direction, 1); var speed = Creature.Stats.GetMoveSpeed(Creature.Brain.IsRunning); Creature.Rigidbody.velocity = direction * speed; } /************************************************************************************************************************/ } }