186 lines
6.9 KiB
C#
186 lines
6.9 KiB
C#
#if !NEOFPS_FORCE_QUALITY && (UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || (UNITY_WSA && NETFX_CORE) || NEOFPS_FORCE_LIGHTWEIGHT)
|
|
#define NEOFPS_LIGHTWEIGHT
|
|
#endif
|
|
|
|
using UnityEngine;
|
|
using NeoFPS.CharacterMotion.MotionData;
|
|
using NeoFPS.CharacterMotion.Parameters;
|
|
using NeoSaveGames.Serialization;
|
|
|
|
namespace NeoFPS.CharacterMotion.States
|
|
{
|
|
[MotionGraphElement("Dashes/Directional Dash", "Dash (Directional)")]
|
|
[HelpURL("https://docs.neofps.com/manual/motiongraphref-mgs-directionaldashstate.html")]
|
|
public class DirectionalDashState : MotionGraphState
|
|
{
|
|
[SerializeField, Tooltip("The target speed for the dash to reach.")]
|
|
private FloatDataReference m_DashSpeed = new FloatDataReference(50f);
|
|
[SerializeField, Tooltip("The acceleration to reach the target dash speed.")]
|
|
private FloatDataReference m_Acceleration = new FloatDataReference(250f);
|
|
[SerializeField, Tooltip("The distance to dash before the state completes.")]
|
|
private FloatDataReference m_DashDistance = new FloatDataReference(0f);
|
|
[SerializeField, Tooltip("The multiplier applied to the max movement speed when strafing")]
|
|
private FloatDataReference m_StrafeMultiplier = new FloatDataReference(0.75f);
|
|
[SerializeField, Tooltip("The multiplier applied to the max movement speed when moving in reverse")]
|
|
private FloatDataReference m_ReverseMultiplier = new FloatDataReference(0.5f);
|
|
|
|
private const float k_TinyValue = 0.001f;
|
|
private const float k_MinInput = 0.05f;
|
|
|
|
public enum DashDirection
|
|
{
|
|
YawRelative,
|
|
MoveRelative
|
|
}
|
|
|
|
private Vector3 m_DashHeading = Vector3.zero;
|
|
private Vector3 m_MotorAcceleration = Vector3.zero;
|
|
private Vector3 m_OutVelocity = Vector3.zero;
|
|
private float m_TotalDashDistance = 0f;
|
|
private float m_TargetSpeed = 0f;
|
|
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 true; }
|
|
}
|
|
|
|
public override bool applyGroundingForce
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
public override bool ignorePlatformMove
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
public bool isInstant
|
|
{
|
|
get { return m_Acceleration.value == 0f; }
|
|
}
|
|
|
|
public override void OnValidate()
|
|
{
|
|
base.OnValidate();
|
|
}
|
|
|
|
public override void OnEnter()
|
|
{
|
|
base.OnEnter();
|
|
|
|
m_Completed = false;
|
|
m_TotalDashDistance = 0f;
|
|
|
|
// Get the dash heading
|
|
m_DashHeading = Vector3.forward;
|
|
if (controller.inputMoveScale > k_MinInput)
|
|
m_DashHeading = new Vector3(controller.inputMoveDirection.x, 0f, controller.inputMoveDirection.y);
|
|
m_DashHeading = characterController.transform.rotation * m_DashHeading;
|
|
|
|
// Get the dash speed
|
|
float directionMultiplier = 1f;
|
|
if (controller.inputMoveDirection.y < 0f)
|
|
directionMultiplier *= Mathf.Lerp(1f, m_ReverseMultiplier.value, -controller.inputMoveDirection.y);
|
|
directionMultiplier *= Mathf.Lerp(1f, m_StrafeMultiplier.value, Mathf.Abs(controller.inputMoveDirection.x));
|
|
m_TargetSpeed = m_DashSpeed.value * directionMultiplier;
|
|
}
|
|
|
|
public override void OnExit()
|
|
{
|
|
base.OnExit();
|
|
m_OutVelocity = Vector3.zero;
|
|
m_TotalDashDistance = 0f;
|
|
m_Completed = false;
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
base.Update();
|
|
|
|
Vector3 flatHeading = m_DashHeading;
|
|
|
|
// Apply ground slope effect
|
|
if (characterController.isGrounded)
|
|
{
|
|
// Get the offset impulse on the ground plane
|
|
Plane p = new Plane(characterController.groundSurfaceNormal, 0f);
|
|
float yOffset = 0f;
|
|
if (p.Raycast(new Ray(flatHeading, characterController.up), out yOffset) && yOffset > k_TinyValue)
|
|
{
|
|
// Apply the offset and clamp the speed to the original value
|
|
flatHeading += characterController.up * yOffset;
|
|
flatHeading.Normalize();
|
|
}
|
|
}
|
|
|
|
// Accelerate to target velocity
|
|
if (m_Acceleration.value > 0f)
|
|
{
|
|
m_OutVelocity = Vector3.SmoothDamp(
|
|
characterController.velocity,
|
|
flatHeading * m_TargetSpeed,
|
|
ref m_MotorAcceleration,
|
|
0.01f,
|
|
m_Acceleration.value
|
|
);
|
|
|
|
m_TotalDashDistance += m_OutVelocity.magnitude * Time.deltaTime;
|
|
if (m_TotalDashDistance > m_DashDistance.value)
|
|
m_Completed = true;
|
|
}
|
|
else
|
|
{
|
|
m_OutVelocity = flatHeading * m_TargetSpeed;
|
|
m_Completed = true;
|
|
}
|
|
}
|
|
|
|
public override void CheckReferences(IMotionGraphMap map)
|
|
{
|
|
m_DashSpeed.CheckReference(map);
|
|
m_Acceleration.CheckReference(map);
|
|
m_DashDistance.CheckReference(map);
|
|
m_StrafeMultiplier.CheckReference(map);
|
|
m_ReverseMultiplier.CheckReference(map);
|
|
base.CheckReferences(map);
|
|
}
|
|
|
|
#region SAVE / LOAD
|
|
|
|
private static readonly NeoSerializationKey k_AccelerationKey = new NeoSerializationKey("acceleration");
|
|
private static readonly NeoSerializationKey k_VelocityKey = new NeoSerializationKey("velocity");
|
|
private static readonly NeoSerializationKey k_DashHeadingKey = new NeoSerializationKey("heading");
|
|
private static readonly NeoSerializationKey k_TotalDashDistanceKey = new NeoSerializationKey("distance");
|
|
|
|
public override void WriteProperties(INeoSerializer writer)
|
|
{
|
|
base.WriteProperties(writer);
|
|
writer.WriteValue(k_AccelerationKey, m_MotorAcceleration);
|
|
writer.WriteValue(k_VelocityKey, m_OutVelocity);
|
|
writer.WriteValue(k_DashHeadingKey, m_DashHeading);
|
|
writer.WriteValue(k_TotalDashDistanceKey, m_TotalDashDistance);
|
|
}
|
|
|
|
public override void ReadProperties(INeoDeserializer reader)
|
|
{
|
|
base.ReadProperties(reader);
|
|
reader.TryReadValue(k_AccelerationKey, out m_MotorAcceleration, m_MotorAcceleration);
|
|
reader.TryReadValue(k_VelocityKey, out m_OutVelocity, m_OutVelocity);
|
|
reader.TryReadValue(k_DashHeadingKey, out m_DashHeading, m_DashHeading);
|
|
reader.TryReadValue(k_TotalDashDistanceKey, out m_TotalDashDistance, m_TotalDashDistance);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |