390 lines
8.4 KiB
C#
390 lines
8.4 KiB
C#
using UnityEngine;
|
|
|
|
public abstract class vp_Controller : vp_Component
|
|
{
|
|
public enum PushForceMode
|
|
{
|
|
Simplified = 0,
|
|
Kinetic = 1
|
|
}
|
|
|
|
protected bool m_Grounded;
|
|
|
|
protected RaycastHit m_GroundHit;
|
|
|
|
protected Transform m_LastGroundHitTransform;
|
|
|
|
protected Transform m_GroundHitTransform;
|
|
|
|
protected float m_FallStartHeight = -99999f;
|
|
|
|
protected float m_FallImpact;
|
|
|
|
protected bool m_OnNewGround;
|
|
|
|
protected bool m_WasFalling;
|
|
|
|
public float PhysicsGravityModifier = 0.2f;
|
|
|
|
protected float m_FallSpeed;
|
|
|
|
public bool MotorFreeFly;
|
|
|
|
public float PhysicsPushForce = 5f;
|
|
|
|
public PushForceMode PhysicsPushMode;
|
|
|
|
public float PhysicsPushInterval = 0.1f;
|
|
|
|
public float PhysicsCrouchHeightModifier = 0.5f;
|
|
|
|
public Vector3 m_Velocity = Vector3.zero;
|
|
|
|
protected Vector3 m_PrevPosition = Vector3.zero;
|
|
|
|
protected Vector3 m_PrevVelocity = Vector3.zero;
|
|
|
|
protected float m_NextAllowedPushTime;
|
|
|
|
protected Transform m_Platform;
|
|
|
|
public Vector3 m_PositionOnPlatform = Vector3.zero;
|
|
|
|
protected float m_LastPlatformAngle;
|
|
|
|
public Vector3 m_LastPlatformPos = Vector3.zero;
|
|
|
|
protected float m_MovingPlatformBodyYawDif;
|
|
|
|
protected float m_NormalHeight;
|
|
|
|
protected Vector3 m_NormalCenter = Vector3.zero;
|
|
|
|
protected float m_CrouchHeight;
|
|
|
|
protected Vector3 m_CrouchCenter = Vector3.zero;
|
|
|
|
protected const float KINETIC_PUSHFORCE_MULTIPLIER = 15f;
|
|
|
|
protected const float CHARACTER_CONTROLLER_SKINWIDTH = 0.08f;
|
|
|
|
protected const float DEFAULT_RADIUS_MULTIPLIER = 0.25f;
|
|
|
|
protected const float FALL_IMPACT_MULTIPLIER = 0.075f;
|
|
|
|
protected const float NOFALL = -99999f;
|
|
|
|
private vp_PlayerEventHandler m_Player;
|
|
|
|
public bool Grounded
|
|
{
|
|
get
|
|
{
|
|
return m_Grounded;
|
|
}
|
|
}
|
|
|
|
public float SkinWidth
|
|
{
|
|
get
|
|
{
|
|
return 0.08f;
|
|
}
|
|
}
|
|
|
|
protected vp_PlayerEventHandler Player
|
|
{
|
|
get
|
|
{
|
|
if (m_Player == null && base.EventHandler != null)
|
|
{
|
|
m_Player = (vp_PlayerEventHandler)base.EventHandler;
|
|
if (m_Player == null)
|
|
{
|
|
Debug.LogError(string.Concat("Error (", this, ") This component requires a ", (!(this is vp_FPController)) ? "vp_PlayerEventHandler" : "vp_FPPlayerEventHandler", " component!"));
|
|
}
|
|
}
|
|
return m_Player;
|
|
}
|
|
}
|
|
|
|
private float FallDistance
|
|
{
|
|
get
|
|
{
|
|
return (m_FallStartHeight == -99999f) ? 0f : Mathf.Max(0f, m_FallStartHeight - base.Transform.position.y);
|
|
}
|
|
}
|
|
|
|
protected virtual Transform OnValue_Platform
|
|
{
|
|
get
|
|
{
|
|
return m_Platform;
|
|
}
|
|
set
|
|
{
|
|
m_Platform = value;
|
|
}
|
|
}
|
|
|
|
protected virtual Vector3 OnValue_Position
|
|
{
|
|
get
|
|
{
|
|
return base.Transform.position;
|
|
}
|
|
set
|
|
{
|
|
SetPosition(value);
|
|
}
|
|
}
|
|
|
|
protected virtual float OnValue_FallSpeed
|
|
{
|
|
get
|
|
{
|
|
return m_FallSpeed;
|
|
}
|
|
set
|
|
{
|
|
m_FallSpeed = value;
|
|
}
|
|
}
|
|
|
|
protected virtual Vector3 OnValue_Velocity
|
|
{
|
|
get
|
|
{
|
|
return m_Velocity;
|
|
}
|
|
set
|
|
{
|
|
m_Velocity = value;
|
|
}
|
|
}
|
|
|
|
protected abstract float OnValue_Radius { get; }
|
|
|
|
protected abstract float OnValue_Height { get; }
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
InitCollider();
|
|
}
|
|
|
|
protected override void Start()
|
|
{
|
|
base.Start();
|
|
RefreshCollider();
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
UpdatePlatformRotation();
|
|
}
|
|
|
|
protected override void FixedUpdate()
|
|
{
|
|
if (Time.timeScale != 0f)
|
|
{
|
|
UpdateForces();
|
|
FixedMove();
|
|
UpdateCollisions();
|
|
UpdatePlatformMove();
|
|
UpdateVelocity();
|
|
}
|
|
}
|
|
|
|
protected virtual void UpdatePlatformMove()
|
|
{
|
|
if (!(m_Platform == null))
|
|
{
|
|
m_PositionOnPlatform = m_Platform.InverseTransformPoint(m_Transform.position);
|
|
m_LastPlatformPos = m_Platform.position;
|
|
}
|
|
}
|
|
|
|
protected virtual void UpdatePlatformRotation()
|
|
{
|
|
if (!(m_Platform == null))
|
|
{
|
|
if (Player.IsLocal.Get())
|
|
{
|
|
m_MovingPlatformBodyYawDif = Mathf.Lerp(m_MovingPlatformBodyYawDif, Mathf.DeltaAngle(Player.Rotation.Get().y, Player.BodyYaw.Get()), Time.deltaTime * 1f);
|
|
}
|
|
Player.Rotation.Set(new Vector2(Player.Rotation.Get().x, Player.Rotation.Get().y - Mathf.DeltaAngle(m_Platform.eulerAngles.y, m_LastPlatformAngle)));
|
|
m_LastPlatformAngle = m_Platform.eulerAngles.y;
|
|
if (Player.IsLocal.Get())
|
|
{
|
|
Player.BodyYaw.Set(Player.BodyYaw.Get() - m_MovingPlatformBodyYawDif);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual void UpdateVelocity()
|
|
{
|
|
m_PrevVelocity = m_Velocity;
|
|
m_Velocity = (base.transform.position - m_PrevPosition) / Time.deltaTime;
|
|
m_PrevPosition = base.Transform.position;
|
|
}
|
|
|
|
public virtual void Stop()
|
|
{
|
|
Player.Move.Send(Vector3.zero);
|
|
Player.InputMoveVector.Set(Vector2.zero);
|
|
m_FallSpeed = 0f;
|
|
m_FallStartHeight = -99999f;
|
|
}
|
|
|
|
protected virtual void InitCollider()
|
|
{
|
|
}
|
|
|
|
protected virtual void RefreshCollider()
|
|
{
|
|
}
|
|
|
|
public virtual void EnableCollider(bool enabled)
|
|
{
|
|
}
|
|
|
|
protected virtual void StoreGroundInfo()
|
|
{
|
|
m_LastGroundHitTransform = m_GroundHitTransform;
|
|
m_Grounded = false;
|
|
m_GroundHitTransform = null;
|
|
if (Physics.SphereCast(new Ray(base.Transform.position + Vector3.up * Player.Radius.Get(), Vector3.down), Player.Radius.Get(), out m_GroundHit, 0.18f, vp_Layer.Mask.ExternalBlockers))
|
|
{
|
|
m_GroundHitTransform = m_GroundHit.transform;
|
|
m_Grounded = m_GroundHitTransform.GetComponent<Collider>() != null;
|
|
}
|
|
if (m_Velocity.y < 0f && m_GroundHitTransform == null && m_LastGroundHitTransform != null && !Player.Jump.Active)
|
|
{
|
|
SetFallHeight(base.Transform.position.y);
|
|
}
|
|
}
|
|
|
|
private void SetFallHeight(float height)
|
|
{
|
|
if (m_FallStartHeight == -99999f && !m_Grounded && !(m_GroundHitTransform != null))
|
|
{
|
|
m_FallStartHeight = height;
|
|
}
|
|
}
|
|
|
|
protected virtual void UpdateForces()
|
|
{
|
|
m_LastGroundHitTransform = m_GroundHitTransform;
|
|
if (m_Grounded && m_FallSpeed <= 0f)
|
|
{
|
|
m_FallSpeed = Physics.gravity.y * (PhysicsGravityModifier * 0.002f) * vp_TimeUtility.AdjustedTimeScale;
|
|
return;
|
|
}
|
|
m_FallSpeed += Physics.gravity.y * (PhysicsGravityModifier * 0.002f) * vp_TimeUtility.AdjustedTimeScale;
|
|
if (m_Velocity.y < 0f && m_PrevVelocity.y >= 0f)
|
|
{
|
|
SetFallHeight(base.Transform.position.y);
|
|
}
|
|
}
|
|
|
|
protected virtual void FixedMove()
|
|
{
|
|
StoreGroundInfo();
|
|
}
|
|
|
|
protected virtual void UpdateCollisions()
|
|
{
|
|
if (Player.Climb.Active)
|
|
{
|
|
m_FallStartHeight = -99999f;
|
|
}
|
|
m_FallImpact = 0f;
|
|
m_OnNewGround = false;
|
|
m_WasFalling = false;
|
|
if (!(m_GroundHitTransform != null) || !(m_GroundHitTransform != m_LastGroundHitTransform))
|
|
{
|
|
return;
|
|
}
|
|
m_OnNewGround = true;
|
|
if (m_LastGroundHitTransform == null)
|
|
{
|
|
m_WasFalling = true;
|
|
if (m_FallStartHeight > base.Transform.position.y && m_Grounded)
|
|
{
|
|
m_FallImpact = ((!MotorFreeFly) ? (FallDistance * 0.075f) : 0f);
|
|
Player.FallImpact.Send(m_FallImpact);
|
|
}
|
|
}
|
|
m_FallStartHeight = -99999f;
|
|
}
|
|
|
|
protected override void LateUpdate()
|
|
{
|
|
base.LateUpdate();
|
|
}
|
|
|
|
public virtual void SetPosition(Vector3 position)
|
|
{
|
|
base.Transform.position = position;
|
|
m_PrevPosition = position;
|
|
vp_Timer.In(0f, delegate
|
|
{
|
|
m_PrevVelocity = vp_3DUtility.HorizontalVector(m_PrevVelocity);
|
|
});
|
|
}
|
|
|
|
public void PushRigidbody(Rigidbody rigidbody, Vector3 moveDirection, PushForceMode pushForcemode, Vector3 point)
|
|
{
|
|
switch (pushForcemode)
|
|
{
|
|
case PushForceMode.Simplified:
|
|
rigidbody.velocity = vp_3DUtility.HorizontalVector(new Vector3(moveDirection.x, 0f, moveDirection.z).normalized) * (PhysicsPushForce / rigidbody.mass);
|
|
break;
|
|
case PushForceMode.Kinetic:
|
|
if (Vector3.Distance(vp_3DUtility.HorizontalVector(base.Transform.position), vp_3DUtility.HorizontalVector(point)) > Player.Radius.Get())
|
|
{
|
|
rigidbody.AddForceAtPosition(vp_3DUtility.HorizontalVector(moveDirection) * (PhysicsPushForce * 15f), point);
|
|
}
|
|
else
|
|
{
|
|
rigidbody.AddForceAtPosition(moveDirection * (PhysicsPushForce * 15f), point);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void PushRigidbody(Rigidbody rigidbody, Vector3 moveDirection, PushForceMode pushForceMode)
|
|
{
|
|
PushRigidbody(rigidbody, moveDirection, pushForceMode, (pushForceMode != PushForceMode.Simplified) ? rigidbody.ClosestPointOnBounds(base.Collider.bounds.center) : Vector3.zero);
|
|
}
|
|
|
|
public void PushRigidbody(Rigidbody rigidbody, Vector3 moveDirection)
|
|
{
|
|
PushRigidbody(rigidbody, moveDirection, PhysicsPushMode, (PhysicsPushMode != PushForceMode.Simplified) ? rigidbody.ClosestPointOnBounds(base.Collider.bounds.center) : Vector3.zero);
|
|
}
|
|
|
|
public void PushRigidbody(Rigidbody rigidbody, Vector3 moveDirection, Vector3 point)
|
|
{
|
|
PushRigidbody(rigidbody, moveDirection, PhysicsPushMode, point);
|
|
}
|
|
|
|
protected virtual void OnMessage_Stop()
|
|
{
|
|
Stop();
|
|
}
|
|
|
|
protected virtual void OnStart_Crouch()
|
|
{
|
|
Player.Run.Stop();
|
|
RefreshCollider();
|
|
}
|
|
|
|
protected virtual void OnStop_Crouch()
|
|
{
|
|
RefreshCollider();
|
|
}
|
|
}
|