// Animancer // Copyright 2020 Kybernetik // #pragma warning disable CS0618 // Type or member is obsolete (for HybridAnimancerComponent in Animancer Lite). using Animancer.Examples.StateMachines.Brains; using UnityEngine; namespace Animancer.Examples.AnimatorControllers { /// /// A which moves the creature according to their /// . /// /// /// This class is very similar to , except that it manages a /// Blend Tree instead of individual s. /// [AddComponentMenu(Strings.MenuPrefix + "Examples/Hybrid - Locomotion State")] [HelpURL(Strings.APIDocumentationURL + ".Examples.AnimatorControllers/LocomotionState")] public sealed class LocomotionState : CreatureState { /************************************************************************************************************************/ [SerializeField] private float _Acceleration = 3; private float _MoveBlend; /************************************************************************************************************************/ private void OnEnable() { Animancer.PlayController(); _MoveBlend = 0; } /************************************************************************************************************************/ 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() { float targetBlend; if (Creature.Brain.MovementDirection == Vector3.zero) targetBlend = 0; else if (Creature.Brain.IsRunning) targetBlend = 1; else targetBlend = 0.5f; _MoveBlend = Mathf.MoveTowards(_MoveBlend, targetBlend, _Acceleration * Time.deltaTime); Animancer.SetFloat("MoveBlend", _MoveBlend); } /************************************************************************************************************************/ /// /// This method is identical to the same method in . /// private void UpdateTurning() { var movement = Creature.Brain.MovementDirection; if (movement == Vector3.zero) return; var targetAngle = Mathf.Atan2(movement.x, movement.z) * Mathf.Rad2Deg; var turnDelta = Creature.Stats.TurnSpeed * Time.deltaTime; 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. /// /// This method is identical to the same method in . /// 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; } /************************************************************************************************************************/ /// /// Normally the class would have a reference to the specific type of /// we want, but for the sake of reusing code from the earlier example, we /// just use a type cast here. /// private HybridAnimancerComponent Animancer { get { return (HybridAnimancerComponent)Creature.Animancer; } } /************************************************************************************************************************/ } }