using UnityEngine; namespace OctoCore.Components { public class OctoCharacterAnimation : MonoBehaviour { [SerializeField] private Animator animator; [SerializeField] private float walkSpeed = 8; [SerializeField] private float runSpeed = 15; [SerializeField, Range(1, 10)] private int sampling = 5; private bool backward; private float backwardSmooth; private float sideSmooth; private float smoothSpeed; private Vector4[] positions; private Vector3 lastStep; private Vector3 direction; private float step = .1f; void OnDrawGizmos() { Gizmos.color = Color.cyan; Gizmos.DrawRay(transform.position + Vector3.up, transform.forward); Gizmos.color = Color.red; Gizmos.DrawRay(transform.position + Vector3.up, direction); } void OnEnable() { positions = new Vector4[sampling + 1]; for (int i = 0; i < sampling; i++) { positions[i] = transform.position; positions[i].z = .002f; } direction = transform.forward; } void Update() { if (lastStep != transform.position && Vector3.Distance(lastStep, transform.position) > step) { Vector3 offset = (lastStep - transform.position).normalized * step; lastStep = transform.position + offset; } direction = Vector3.Lerp(direction, (transform.position - lastStep).normalized, Time.deltaTime * 10); float speed = GetSpeed(); smoothSpeed = Mathf.Lerp(smoothSpeed, speed, Time.deltaTime * 10); float move = Mathf.Clamp01(smoothSpeed / walkSpeed); float run = Mathf.Clamp01((smoothSpeed - walkSpeed) / (runSpeed - walkSpeed)); float dot = Vector3.Dot(transform.forward, direction.normalized); Vector3 crs = Vector3.Cross(transform.forward, direction.normalized); backward = dot < 0; backwardSmooth = Mathf.Lerp(backwardSmooth, backward ? 1 : 0, Time.deltaTime * 10); sideSmooth = Mathf.Lerp(sideSmooth, (1 - Mathf.Abs(dot)) * Mathf.Sign(transform.InverseTransformDirection(crs).y) * direction.magnitude, Time.deltaTime * 20); run *= 1 - backwardSmooth; run *= 1 - Mathf.Abs(sideSmooth); //Debug.Log(dot); animator.SetFloat("move", Mathf.Sqrt(move)); animator.SetFloat("run", run); animator.SetFloat("backward", backwardSmooth); animator.SetFloat("side", sideSmooth); } float GetSpeed() { float offset = 0; float delta = 0; for (int i = 0; i < positions.Length - 1; i++) { offset += Vector3.Distance(positions[i], positions[i + 1]); delta += positions[i].w; } for (int i = positions.Length - 1; i > 0; i--) positions[i] = positions[i - 1]; positions[0] = transform.position; positions[0].w = Time.deltaTime; if (offset > 0 && delta > 0) return offset / (delta / 3.6f); else return 0; } } }