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

176 lines
5.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("Swimming/Swim Submerge", "Submerge")]
[HelpURL("https://docs.neofps.com/manual/motiongraphref-mgs-swimsubmergestate.html")]
public class SwimSubmergeState : MotionGraphState
{
[SerializeField, Tooltip("The transform parameter which contains the transform of the water zone object")]
private TransformParameter m_WaterZoneParameter = null;
[SerializeField, Tooltip("The distance below the surface of the water to submerge")]
private float m_SubmergeDistance = 0.5f;
[SerializeField, Tooltip("The time to take while submerging (will be instant if already below submerge distance)")]
private float m_Duration = 1f;
private Vector3 m_OutMoveVector = Vector3.zero;
private Transform m_WaterZoneTransform = null;
private IWaterZone m_WaterZone = null;
private Vector3 m_EntryVelocity = Vector3.zero;
private float m_EntryHeight = 0f;
private float m_Lerp = 0f;
public override bool CheckCanEnter()
{
return m_WaterZoneParameter != null;
}
public override Vector3 moveVector
{
get { return m_OutMoveVector; }
}
public override bool applyGravity
{
get { return false; }
}
public override bool applyGroundingForce
{
get { return false; }
}
public override bool ignorePlatformMove
{
get { return false; }
}
public override bool completed
{
get { return m_Lerp >= 1f; }
}
public override void OnValidate()
{
base.OnValidate();
m_SubmergeDistance = Mathf.Clamp(m_SubmergeDistance, 0.1f, 10f);
m_Duration = Mathf.Clamp(m_Duration, 0.1f, 10f);
}
public override void OnEnter()
{
base.OnEnter();
CheckWaterZone();
// Get the water surface from the top sphere of the character
var highest = WaterZoneHelpers.GetHighestSphereCenter(controller);
highest.y += characterController.radius;
var surface = m_WaterZone.SurfaceInfoAtPosition(highest);
// Get the height relative to the surface
m_EntryHeight = highest.y - surface.height;
if (m_EntryHeight < -m_SubmergeDistance)
m_Lerp = 1f;
else
{
// Reset the lerp
m_Lerp = 0f;
// Get the entry velocity
m_EntryVelocity = characterController.velocity;
m_EntryVelocity.y = 0f;
}
}
public override void OnExit()
{
base.OnExit();
m_Lerp = 0f;
m_OutMoveVector = Vector3.zero;
}
void CheckWaterZone()
{
// Get the water zone
if (m_WaterZoneParameter != null)
{
if (m_WaterZoneTransform != m_WaterZoneParameter.value)
{
m_WaterZoneTransform = m_WaterZoneParameter.value;
if (m_WaterZoneTransform != null)
m_WaterZone = m_WaterZoneTransform.GetComponent<IWaterZone>();
}
}
}
public override void Update()
{
base.Update();
CheckWaterZone();
// Update lerp
m_Lerp += Time.deltaTime / m_Duration;
if (m_Lerp > 1f)
m_Lerp = 1f;
// Decelerate horizontal velocity
var horizontalV = m_EntryVelocity;// * (1f - m_Lerp * m_Lerp);
m_OutMoveVector = horizontalV * Time.deltaTime;
// Get the water surface from the top sphere of the character
var highest = WaterZoneHelpers.GetHighestSphereCenter(controller);
highest.y += characterController.radius;
var surface = m_WaterZone.SurfaceInfoAtPosition(highest);
// Get the target height relative to the surface
var targetHeight = Mathf.Lerp(m_EntryHeight, -0.1f, EasingFunctions.EaseInOutQuadratic(m_Lerp));
var actualHeight = surface.height + targetHeight;
// Add lerped height to move vector
m_OutMoveVector.y = actualHeight - highest.y;
// Flow?
}
public override void CheckReferences(IMotionGraphMap map)
{
m_WaterZoneParameter = map.Swap(m_WaterZoneParameter);
base.CheckReferences(map);
}
#region SAVE / LOAD
private static readonly NeoSerializationKey k_EntryVelocityKey = new NeoSerializationKey("entryVelocity");
private static readonly NeoSerializationKey k_EntryHeightKey = new NeoSerializationKey("entryHeight");
private static readonly NeoSerializationKey k_LerpKey = new NeoSerializationKey("lerp");
public override void WriteProperties(INeoSerializer writer)
{
base.WriteProperties(writer);
writer.WriteValue(k_EntryVelocityKey, m_EntryVelocity);
writer.WriteValue(k_EntryHeightKey, m_EntryHeight);
writer.WriteValue(k_LerpKey, m_Lerp);
}
public override void ReadProperties(INeoDeserializer reader)
{
base.ReadProperties(reader);
reader.TryReadValue(k_EntryVelocityKey, out m_EntryVelocity, m_EntryVelocity);
reader.TryReadValue(k_EntryHeightKey, out m_EntryHeight, m_EntryHeight);
reader.TryReadValue(k_LerpKey, out m_Lerp, m_Lerp);
}
#endregion
}
}