ECM2
This commit is contained in:
216
Assets/ECM2/Examples/Slide/Scripts/PlayerCharacter.cs
Normal file
216
Assets/ECM2/Examples/Slide/Scripts/PlayerCharacter.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ECM2.Examples.Slide
|
||||
{
|
||||
/// <summary>
|
||||
/// This example extends a Character (through inheritance) implementing a slide mechanic.
|
||||
/// </summary>
|
||||
|
||||
public class PlayerCharacter : Character
|
||||
{
|
||||
[Space(15.0f)]
|
||||
public float slideImpulse = 20.0f;
|
||||
public float slideDownAcceleration = 20.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Our custom movement mode(s) id(s).
|
||||
/// </summary>
|
||||
|
||||
enum ECustomMovementMode
|
||||
{
|
||||
Sliding = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If sliding, return max walk speed as our speed limit.
|
||||
/// </summary>
|
||||
|
||||
public override float GetMaxSpeed()
|
||||
{
|
||||
return IsSliding() ? maxWalkSpeed : base.GetMaxSpeed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If sliding, limit acceleration.
|
||||
/// </summary>
|
||||
|
||||
public override float GetMaxAcceleration()
|
||||
{
|
||||
return IsSliding() ? maxAcceleration * 0.1f : base.GetMaxAcceleration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override IsWalking (aka: grounded movement mode) to add Sliding movement mode support,
|
||||
/// otherwise crouch, jump will fail while sliding due its conditions checking if IsWalking.
|
||||
/// </summary>
|
||||
|
||||
public override bool IsWalking()
|
||||
{
|
||||
return IsSliding() || base.IsWalking();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the Character sliding?
|
||||
/// </summary>
|
||||
|
||||
public bool IsSliding()
|
||||
{
|
||||
return movementMode == MovementMode.Custom && customMovementMode == (int)ECustomMovementMode.Sliding;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the character can slide in its current state.
|
||||
/// </summary>
|
||||
|
||||
protected virtual bool CanSlide()
|
||||
{
|
||||
// Slide is tied to crouch, if not crouching cant slide!
|
||||
|
||||
if (!IsGrounded())
|
||||
return false;
|
||||
|
||||
// Check allowed slide speed threshold
|
||||
|
||||
float sqrSpeed = velocity.sqrMagnitude;
|
||||
float slideSpeedThreshold = maxWalkSpeedCrouched * maxWalkSpeedCrouched;
|
||||
|
||||
return sqrSpeed >= slideSpeedThreshold * 1.02f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate sliding direction vector.
|
||||
/// </summary>
|
||||
|
||||
protected virtual Vector3 CalcSlideDirection()
|
||||
{
|
||||
Vector3 slideDirection = GetMovementDirection();
|
||||
if (slideDirection.isZero())
|
||||
slideDirection = GetVelocity();
|
||||
else if (slideDirection.isZero())
|
||||
slideDirection = GetForwardVector();
|
||||
|
||||
slideDirection = ConstrainInputVector(slideDirection);
|
||||
|
||||
return slideDirection.normalized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to perform a requested slide or
|
||||
/// stop it if requested or cant continue sliding.
|
||||
/// </summary>
|
||||
|
||||
protected virtual void CheckSlideInput()
|
||||
{
|
||||
bool isSliding = IsSliding();
|
||||
bool wantsToSlide = crouchInputPressed;
|
||||
|
||||
if (!isSliding && wantsToSlide && CanSlide())
|
||||
{
|
||||
SetMovementMode(MovementMode.Custom, (int)ECustomMovementMode.Sliding);
|
||||
}
|
||||
else if (isSliding && (!wantsToSlide || !CanSlide()))
|
||||
{
|
||||
SetMovementMode(MovementMode.Walking);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Sliding enter / exit.
|
||||
/// </summary>
|
||||
|
||||
protected override void OnMovementModeChanged(MovementMode prevMovementMode, int prevCustomMode)
|
||||
{
|
||||
// Call base method implementation
|
||||
|
||||
base.OnMovementModeChanged(prevMovementMode, prevCustomMode);
|
||||
|
||||
// Enter sliding movement mode...
|
||||
|
||||
if (IsSliding())
|
||||
{
|
||||
// Apply initial slide impulse
|
||||
|
||||
Vector3 slideDirection = CalcSlideDirection();
|
||||
characterMovement.velocity += slideDirection * slideImpulse;
|
||||
|
||||
// Disable Character rotation
|
||||
|
||||
SetRotationMode(RotationMode.None);
|
||||
}
|
||||
|
||||
// Exit sliding movement mode...
|
||||
|
||||
bool wasSliding = prevMovementMode == MovementMode.Custom &&
|
||||
prevCustomMode == (int)ECustomMovementMode.Sliding;
|
||||
|
||||
if (wasSliding)
|
||||
{
|
||||
// Re-enable Character rotation
|
||||
|
||||
SetRotationMode(RotationMode.OrientRotationToMovement);
|
||||
|
||||
// If falling, make sure its velocity do not exceed maxWalkSpeed
|
||||
|
||||
if (IsFalling())
|
||||
{
|
||||
Vector3 worldUp = -GetGravityDirection();
|
||||
Vector3 verticalVelocity = Vector3.Project(velocity, worldUp);
|
||||
Vector3 lateralVelocity = Vector3.ClampMagnitude(velocity - verticalVelocity, maxWalkSpeed);
|
||||
|
||||
characterMovement.velocity = lateralVelocity + verticalVelocity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnBeforeSimulationUpdate(float deltaTime)
|
||||
{
|
||||
// Call base method implementation
|
||||
|
||||
base.OnBeforeSimulationUpdate(deltaTime);
|
||||
|
||||
// Attempts to do a requested slide
|
||||
|
||||
CheckSlideInput();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update Character's velocity while SLIDING on walkable surfaces.
|
||||
/// </summary>
|
||||
|
||||
protected virtual void SlidingMovementMode(float deltaTime)
|
||||
{
|
||||
// Limit input to lateral movement only (strafing)
|
||||
|
||||
Vector3 desiredVelocity = Vector3.Project(GetDesiredVelocity(), GetRightVector());
|
||||
|
||||
// Calculate new velocity
|
||||
|
||||
characterMovement.velocity =
|
||||
CalcVelocity(characterMovement.velocity, desiredVelocity, groundFriction * 0.2f, false, deltaTime);
|
||||
|
||||
// Apply slide down acceleration
|
||||
|
||||
Vector3 slideDownDirection =
|
||||
Vector3.ProjectOnPlane(GetGravityDirection(), characterMovement.groundNormal).normalized;
|
||||
|
||||
characterMovement.velocity += slideDownAcceleration * deltaTime * slideDownDirection;
|
||||
|
||||
// Apply downwards force
|
||||
|
||||
if (applyStandingDownwardForce)
|
||||
ApplyDownwardsForce();
|
||||
}
|
||||
|
||||
protected override void CustomMovementMode(float deltaTime)
|
||||
{
|
||||
// Call base method implementation
|
||||
|
||||
base.CustomMovementMode(deltaTime);
|
||||
|
||||
// Sliding custom movement mode
|
||||
|
||||
if (customMovementMode == (int)ECustomMovementMode.Sliding)
|
||||
SlidingMovementMode(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user