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

140 lines
5.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("Wall Movement/Wall Run (Up)", "VertWallRun")]
[HelpURL("https://docs.neofps.com/manual/motiongraphref-mgs-verticalwallrunstate.html")]
public class VerticalWallRunState : MotionGraphState
{
[SerializeField, Tooltip("A parameter containing the wall normal vector the character is running up")]
private VectorParameter m_WallNormal = null;
[SerializeField, Tooltip("An upward speed boost applied when entering the state")]
private FloatDataReference m_UpBoost = new FloatDataReference(3f);
[SerializeField, Tooltip("The upward speed can not be boosted above this value (though it can start higher than this)")]
private FloatDataReference m_MaxBoostSpeed = new FloatDataReference(10f);
[SerializeField, Tooltip("A multiplier that is used to reduce the effects of gravity when running up the wall")]
private FloatDataReference m_GravityMultiplier = new FloatDataReference(0.5f);
private Vector3 m_OutVelocity = Vector3.zero;
private bool m_Boost = false;
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 false; }
}
public override bool ignorePlatformMove
{
get { return true; }
}
public override void OnEnter()
{
base.OnEnter();
m_Completed = false;
m_Boost = true;
}
public override void OnExit()
{
base.OnExit();
m_Completed = false;
m_OutVelocity = Vector3.zero;
}
public override void Update()
{
base.Update();
if (!m_Completed)
{
if (m_Boost)
{
// Apply boost if up velocity is below max
float upVelocity = Vector3.Dot(characterController.velocity, characterController.up);
upVelocity = Mathf.Min(m_MaxBoostSpeed.value, upVelocity + m_UpBoost.value);
m_OutVelocity = characterController.up * upVelocity;
m_Boost = false;
}
else
{
// Test wall collision (completed if no collision)
if (m_WallNormal != null && m_WallNormal.value.sqrMagnitude > 0.5f)
{
RaycastHit hit;
if (characterController.SphereCast(0f, -m_WallNormal.value * 0.1f, Space.World, out hit, PhysicsFilter.Masks.CharacterBlockers, QueryTriggerInteraction.Ignore))
m_WallNormal.value = hit.normal;
else
m_Completed = true;
}
// Get wall velocity
m_OutVelocity = Vector3.ProjectOnPlane(characterController.velocity, m_WallNormal.value);
// Add reduced gravity effect
m_OutVelocity += (characterController.gravity * Time.deltaTime * m_GravityMultiplier.value);
// Check if reached apex & set completed if true
if (Vector3.Dot(m_OutVelocity, characterController.up) < 0f)
m_Completed = true;
}
}
}
public override void CheckReferences(IMotionGraphMap map)
{
m_WallNormal = map.Swap(m_WallNormal);
m_UpBoost.CheckReference(map);
m_MaxBoostSpeed.CheckReference(map);
m_GravityMultiplier.CheckReference(map);
base.CheckReferences(map);
}
#region SAVE / LOAD
private static readonly NeoSerializationKey k_CompletedKey = new NeoSerializationKey("completed");
private static readonly NeoSerializationKey k_VelocityKey = new NeoSerializationKey("velocity");
public override void WriteProperties(INeoSerializer writer)
{
base.WriteProperties(writer);
writer.WriteValue(k_VelocityKey, m_OutVelocity);
writer.WriteValue(k_CompletedKey, m_Completed);
}
public override void ReadProperties(INeoDeserializer reader)
{
base.ReadProperties(reader);
reader.TryReadValue(k_VelocityKey, out m_OutVelocity, m_OutVelocity);
reader.TryReadValue(k_CompletedKey, out m_Completed, m_Completed);
}
#endregion
}
}