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

181 lines
7.1 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("Airborne/Fly", "Fly")]
[HelpURL("https://docs.neofps.com/manual/motiongraphref-mgs-flystate.html")]
public class FlyState : MotionGraphState
{
[SerializeField, Tooltip("The crouch hold parameter (used for flying down)")]
private SwitchParameter m_CrouchHold = null;
[SerializeField, Tooltip("The crouch hold parameter (used for flying up)")]
private SwitchParameter m_JumpHold = null;
[SerializeField, Tooltip("The top movement speed (for keyboard input or max analog input)")]
private FloatDataReference m_TopSpeed = new FloatDataReference(5);
[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);
[SerializeField, Tooltip("The multiplier applied to the max movement speed when moving up or down")]
private FloatDataReference m_UpDownMultiplier = new FloatDataReference(0.25f);
[SerializeField, Tooltip("The maximum acceleration")]
private FloatDataReference m_Acceleration = new FloatDataReference(50f);
[SerializeField, Tooltip("How does the camera pitch affect the movement")]
private PitchMode m_PitchMode = PitchMode.UpDownIgnores;
[SerializeField, Range(0f, 1f), Tooltip("The amount of damping to apply when changing direction or speed")]
private float m_Damping = 0.25f;
private const float k_TinyValue = 0.001f;
private Vector3 m_MotorAcceleration = Vector3.zero;
private Vector3 m_OutVelocity = Vector3.zero;
public enum PitchMode
{
UpDownIgnores,
AffectsAllAxes,
Ignore
}
public override Vector3 moveVector
{
get { return m_OutVelocity * Time.deltaTime; }
}
public override bool applyGravity
{
get { return false; }
}
public override bool applyGroundingForce
{
get { return false; }
}
public override bool ignorePlatformMove
{
get { return false; }
}
public override void OnValidate()
{
base.OnValidate();
m_TopSpeed.ClampValue(0.1f, 50f);
m_StrafeMultiplier.ClampValue(0f, 2f);
m_ReverseMultiplier.ClampValue(0f, 2f);
m_UpDownMultiplier.ClampValue(0f, 2f);
m_Acceleration.ClampValue(0f, 1000f);
}
public override void OnEnter()
{
base.OnEnter();
}
public override void OnExit()
{
base.OnExit();
m_OutVelocity = Vector3.zero;
}
public override void Update()
{
base.Update();
// Get movement axes
Vector3 up = characterController.up;
Vector3 forward = characterController.forward;
Vector3 right = characterController.right;
// Modify axes based on pitch settings
switch (m_PitchMode)
{
case PitchMode.UpDownIgnores:
forward = Quaternion.AngleAxis(-controller.aimController.pitch, right) * forward;
break;
case PitchMode.AffectsAllAxes:
Quaternion pitchRotation = Quaternion.AngleAxis(-controller.aimController.pitch, right);
up = pitchRotation * up;
forward = pitchRotation * forward;
break;
}
// Calculate speed based on move direction
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));
// Get target velocity
float topSpeed = m_TopSpeed.value;
Vector3 targetVelocity = Vector3.zero;
targetVelocity += forward * controller.inputMoveDirection.y * topSpeed * directionMultiplier;
targetVelocity += right * controller.inputMoveDirection.x * topSpeed * directionMultiplier;
// Add up/down speed
float upDown = 0f;
if (m_JumpHold != null && m_JumpHold.on)
upDown += 1f;
if (m_CrouchHold != null && m_CrouchHold.on)
upDown -= 1f;
if (upDown != 0f)
targetVelocity += up * upDown * m_UpDownMultiplier.value * m_TopSpeed.value;
// Accelerate if required
float acceleration = m_Acceleration.value;
if (acceleration < k_TinyValue)
m_OutVelocity = targetVelocity;
else
{
var currentVelocity = characterController.velocity;
if (targetVelocity != currentVelocity)
{
// Get maximum acceleration
float maxAccel = acceleration * directionMultiplier;
// Accelerate the velocity
m_OutVelocity = Vector3.SmoothDamp(currentVelocity, targetVelocity, ref m_MotorAcceleration, Mathf.Lerp(0.05f, 0.25f, m_Damping), maxAccel);
}
}
}
public override void CheckReferences(IMotionGraphMap map)
{
m_CrouchHold = map.Swap(m_CrouchHold);
m_JumpHold = map.Swap(m_JumpHold);
m_TopSpeed.CheckReference(map);
m_StrafeMultiplier.CheckReference(map);
m_ReverseMultiplier.CheckReference(map);
m_UpDownMultiplier.CheckReference(map);
m_Acceleration.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");
public override void WriteProperties(INeoSerializer writer)
{
base.WriteProperties(writer);
writer.WriteValue(k_AccelerationKey, m_MotorAcceleration);
writer.WriteValue(k_VelocityKey, m_OutVelocity);
}
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);
}
#endregion
}
}