projectEli/Assets/NeoFPS/Core/Weapons/Shared/ProceduralSprintAnimationHandler.cs
2022-11-06 20:28:33 -05:00

159 lines
6.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using NeoFPS.CharacterMotion;
using NeoFPS.CharacterMotion.Parameters;
using UnityEngine;
namespace NeoFPS
{
public abstract class ProceduralSprintAnimationHandler : BaseSprintAnimationHandler, IAdditiveTransform
{
[SerializeField, Tooltip("The neutral weapon / item position in sprint pose before bob is applied.")]
private Vector3 m_SprintOriginPos = new Vector3(0.05f, -0.05f, 0.05f);
[SerializeField, Tooltip("The neutral weapon / item rotation in sprint pose before bob is applied.")]
private Vector3 m_SprintOriginRot = new Vector3(10f, -30f, 15f);
[SerializeField, Tooltip("The peak position offset of the step cycle on the z and y axes (z does not change).")]
private Vector2 m_SprintOffset = new Vector2(0.05f, 0.025f);
[SerializeField, Tooltip("The peak rotation of the step cycle on each axis.")]
private Vector3 m_SprintRotation = new Vector3(2.5f, 5f, 5f);
[SerializeField, Range (-0.5f, 0.5f), Tooltip("The offset in terms of one full step cycle (left and right) for the timing of the rotation. Positive means after the position, Negative means before.")]
private float m_RotationDesync = 0.1f;
[SerializeField, Tooltip("The speed at which the full sprint animation strength is reached. This fades out the rotation aspect as the character slows down.")]
private float m_FullStrengthSpeed = 10f;
private ICharacterStepTracker m_StepTracker = null;
private IPoseHandler m_PoseHandler = null;
private IAdditiveTransformHandler m_AdditiveTransformHandler = null;
private bool m_InSprintPose = false;
public Quaternion rotation
{
get;
private set;
}
public Vector3 position
{
get;
private set;
}
public bool bypassPositionMultiplier
{
get { return true; }
}
public bool bypassRotationMultiplier
{
get { return true; }
}
protected override void OnValidate()
{
base.OnValidate();
m_FullStrengthSpeed = Mathf.Clamp(m_FullStrengthSpeed, 1f, 100f);
// Clamp animation offsets
m_SprintOriginPos.x = Mathf.Clamp(m_SprintOriginPos.x, -1f, 1f);
m_SprintOriginPos.y = Mathf.Clamp(m_SprintOriginPos.y, -1f, 1f);
m_SprintOriginPos.z = Mathf.Clamp(m_SprintOriginPos.z, -1f, 1f);
m_SprintOriginRot.x = Mathf.Clamp(m_SprintOriginRot.x, -90f, 90f);
m_SprintOriginRot.y = Mathf.Clamp(m_SprintOriginRot.y, -90f, 90f);
m_SprintOriginRot.z = Mathf.Clamp(m_SprintOriginRot.z, -90f, 90f);
m_SprintOffset.x = Mathf.Clamp(m_SprintOffset.x, -1f, 1f);
m_SprintOffset.y = Mathf.Clamp(m_SprintOffset.y, -1f, 1f);
m_SprintRotation.x = Mathf.Clamp(m_SprintRotation.x, -45f, 45f);
m_SprintRotation.y = Mathf.Clamp(m_SprintRotation.y, -45f, 45f);
m_SprintRotation.z = Mathf.Clamp(m_SprintRotation.z, -90f, 90f);
}
protected override void Awake()
{
m_PoseHandler = GetComponent<IPoseHandler>();
m_AdditiveTransformHandler = GetComponentInChildren<IAdditiveTransformHandler>();
base.Awake();
}
protected override void AttachToWielder(ICharacter wielder)
{
base.AttachToWielder(wielder);
m_StepTracker = wielder.GetComponent<ICharacterStepTracker>();
}
protected override void Update()
{
base.Update();
}
protected override void OnSprintStateChanged(SprintState s)
{
switch (s)
{
case SprintState.EnteringSprint:
if (!m_InSprintPose)
{
m_PoseHandler.SetPose(m_SprintOriginPos, Quaternion.Euler(m_SprintOriginRot), inTime);
m_AdditiveTransformHandler.ApplyAdditiveEffect(this);
m_InSprintPose = true;
}
break;
case SprintState.ExitingSprint:
if (m_InSprintPose)
{
m_PoseHandler.ResetPose(outTime);
m_InSprintPose = false;
}
break;
case SprintState.Sprinting:
if (!m_InSprintPose)
{
m_PoseHandler.SetPose(m_SprintOriginPos, Quaternion.Euler(m_SprintOriginRot), 0f);
m_AdditiveTransformHandler.ApplyAdditiveEffect(this);
m_InSprintPose = true;
}
break;
case SprintState.NotSprinting:
if (m_InSprintPose)
{
m_PoseHandler.ResetPose(0f);
m_InSprintPose = false;
}
m_AdditiveTransformHandler.RemoveAdditiveEffect(this);
break;
}
}
public void UpdateTransform()
{
// Get sprint cycle (from motion graph or internally if not found)
float stepCycle = 0f;
if (m_StepTracker != null)
stepCycle = m_StepTracker.stepCounter * 0.5f;
if (sprintState != SprintState.NotSprinting)
{
float sin = Mathf.Sin(stepCycle * Mathf.PI * 2f);
position = new Vector3(
m_SprintOffset.x * sin,
m_SprintOffset.y * Mathf.Abs(sin),
0f
);
sin = Mathf.Sin((stepCycle + m_RotationDesync) * Mathf.PI * 2f);
rotation = Quaternion.Euler(
m_SprintRotation.x * sin,
m_SprintRotation.y * Mathf.Abs(sin),
m_SprintRotation.z * sin
);
if (sprintState == SprintState.EnteringSprint || sprintState == SprintState.ExitingSprint)
position *= sprintWeight * sprintWeight;
float sprintStrength = sprintWeight * sprintWeight * Mathf.Clamp01(sprintSpeed / m_FullStrengthSpeed);
rotation = Quaternion.Lerp(Quaternion.identity, rotation, sprintStrength);
}
}
}
}