projectEli/Assets/NeoFPS/Core/MotionGraphs/States/ImpulseState.cs
2022-11-06 20:28:33 -05:00

124 lines
4.1 KiB
C#

using UnityEngine;
using NeoFPS.CharacterMotion.MotionData;
using NeoFPS.CharacterMotion.Parameters;
namespace NeoFPS.CharacterMotion.States
{
[MotionGraphElement("Instant/Impulse", "Impulse")]
[HelpURL("https://docs.neofps.com/manual/motiongraphref-mgs-impulsestate.html")]
public class ImpulseState : MotionGraphState
{
[SerializeField, Tooltip("The velocity impulse to apply")]
private VectorParameter m_Impulse = null;
[SerializeField, Tooltip("The coordinate space to apply the impulse in.")]
private Space m_FrameOfReference = Space.Self;
[SerializeField, Tooltip("How should the impulse be applied. Additive will add the impulse velocity to the original velocity. ReplaceVelocity will ignore the original velocity and use the impulse alone.")]
private ImpulseMode m_ImpulseMode = ImpulseMode.Additive;
[SerializeField, Tooltip("If true, the impulse vector will be aligned onto the ground plane")]
private bool m_GroundConstrained = false;
private const float k_TinyValue = 0.001f;
public enum ImpulseMode
{
Additive,
ReplaceVelocity
}
private Vector3 m_OutVelocity = Vector3.zero;
private bool m_Completed = false;
public override bool completed
{
get { return m_Completed; }
}
public override Vector3 moveVector
{
get { return m_OutVelocity * Time.deltaTime; }
}
public override bool applyGravity
{
get { return false; }
}
public override bool applyGroundingForce
{
get { return m_GroundConstrained; }
}
public override bool ignorePlatformMove
{
get { return false; }
}
public override void OnValidate()
{
base.OnValidate();
}
public override void OnEnter()
{
base.OnEnter();
m_Completed = false;
}
public override void OnExit()
{
base.OnExit();
m_Completed = false;
m_OutVelocity = Vector3.zero;
}
public override void Update()
{
base.Update();
if (!m_Completed)
{
if (m_Impulse != null)
{
// Align the impulse vector to the character if required
Vector3 impulse = m_Impulse.value;
if (m_FrameOfReference == Space.Self)
impulse = controller.localTransform.rotation * impulse;
// Constrain the impulse vector to the ground surface if required
if (m_GroundConstrained && characterController.isGrounded)
{
// Get the offset impulse on the ground plane
Plane p = new Plane(characterController.groundSurfaceNormal, 0f);
float yOffset = 0f;
p.Raycast(new Ray(impulse, characterController.up), out yOffset);
// Check if an offset is required
if (yOffset > k_TinyValue)
{
// Apply the offset and clamp the speed to the original value
float impulseMag = impulse.magnitude;
impulse += characterController.up * yOffset;
impulse = Vector3.ClampMagnitude(impulse, impulseMag);
}
}
// Calculate the velocity
if (m_ImpulseMode == ImpulseMode.Additive)
m_OutVelocity = characterController.velocity + impulse;
else
m_OutVelocity = impulse;
}
else
m_OutVelocity = characterController.velocity;
m_Completed = true;
}
}
public override void CheckReferences(IMotionGraphMap map)
{
m_Impulse = map.Swap(m_Impulse);
base.CheckReferences(map);
}
}
}