// 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; }
}
/************************************************************************************************************************/
}
}