124 lines
4.1 KiB
C#
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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|