181 lines
7.1 KiB
C#
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
|
|||
|
}
|
|||
|
}
|