Added wall running

This commit is contained in:
2025-03-28 11:25:24 +00:00
parent 12ed9fd42f
commit 611fe6c014
3 changed files with 171 additions and 83 deletions

View File

@@ -10,5 +10,5 @@ PhysicMaterial:
dynamicFriction: 0
staticFriction: 0
bounciness: 0
frictionCombine: 0
bounceCombine: 0
frictionCombine: 1
bounceCombine: 1

View File

@@ -615,6 +615,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: ae4c295274f6a0645b04723c79481e73, type: 3}
m_Name:
m_EditorClassIdentifier:
m_State: 0
m_MoveSpeed: 7
m_GroundDrag: 5
m_AirDrag: 4
@@ -629,7 +630,10 @@ MonoBehaviour:
m_SlideScaler: 0.6
m_SlideDrag: 3
m_SlideSpeed: 10
m_JumpForce: 10
m_JumpForce: 20
m_WallRunSpeed: 10
m_WallCheckDistance: 1.5
m_DistanceOfFloorToWallRide: 0.1
m_JumpKey: 32
m_SlideKey: 99
m_Body: {fileID: 1174770952}

View File

@@ -1,8 +1,18 @@
using UnityEngine;
using UnityEngine.UI;
public enum PlayerState
{
RUNNING,
SLIDING,
WALL_RUNNING
}
public class PlayerMovement : MonoBehaviour
{
[Header("VIEWABLE ONLY")]
[SerializeField] PlayerState m_State = PlayerState.RUNNING;
[Header("General Settings")]
[SerializeField] float m_MoveSpeed;
[SerializeField] float m_GroundDrag;
@@ -22,6 +32,11 @@ public class PlayerMovement : MonoBehaviour
[Header("Jump Settings")]
[SerializeField] float m_JumpForce;
[Header("Wall Run Settings")]
[SerializeField] float m_WallRunSpeed;
[SerializeField] float m_WallCheckDistance;
[SerializeField] float m_DistanceOfFloorToWallRide;
[Header("KeyBinds")]
[SerializeField] KeyCode m_JumpKey;
[SerializeField] KeyCode m_SlideKey;
@@ -37,20 +52,32 @@ public class PlayerMovement : MonoBehaviour
// Current direction the user has inputted
Vector2 m_Input;
// The direction to move the player
Vector3 m_MoveDir;
// Player state tracker
bool m_Grounded = false;
bool m_OnSlope = false;
bool m_Sliding = false;
// Key state trackers
bool m_JumpKeyPressed = false;
bool m_SlidingKeyPressed = false;
// The direction to move the player
Vector3 m_MoveDir;
// Player state trackers
bool m_Grounded = false;
bool m_OnSlope = false;
// Trackers for the walls
bool m_HitLhsWall = false;
bool m_HitRhsWall = false;
// Tracks if the distance of the ground is big enough
bool m_IsFarEnoughOffGroundToWallRide = false;
// Timer for slide boost duration left
int m_TicksOfSlideBoostLeft = 0;
// Raycast hit objects
RaycastHit m_GroundHit;
RaycastHit m_SlopeHit;
RaycastHit m_LhsWall;
RaycastHit m_RhsWall;
// Start is called before the first frame update
private void Start()
@@ -76,22 +103,20 @@ public class PlayerMovement : MonoBehaviour
// Applies drag to the player
private void ApplyDrag()
{
// Only applies ground drag if the player is on the floor
if (m_Grounded)
switch (m_State)
{
m_Body.drag = m_GroundDrag;
}
case PlayerState.SLIDING:
m_Body.drag = m_SlideDrag;
break;
// Applies sliding drag if sliding <- Very useful comment
if (m_Sliding)
{
m_Body.drag = m_SlideDrag;
}
default:
// Applies different drag depending on if the player is on the ground or not
if (m_Grounded)
{ m_Body.drag = m_GroundDrag; }
else
{ m_Body.drag = m_AirDrag; }
// Else it applies the air drag to the player
else
{
m_Body.drag = m_AirDrag;
break;
}
}
@@ -99,9 +124,16 @@ public class PlayerMovement : MonoBehaviour
private void Update()
{
// Performs raycasts to see what the player is standing on
m_Grounded = Physics.Raycast(transform.position, Vector3.down, m_PlayerHeight * 0.5f + 0.3f, m_GroundMask);
m_Grounded = Physics.Raycast(transform.position, Vector3.down, out m_GroundHit, m_PlayerHeight * 0.5f + 0.3f, m_GroundMask);
m_OnSlope = Physics.Raycast(transform.position, Vector3.down, out m_SlopeHit, m_PlayerHeight * 0.5f + 0.3f, m_SlopeMask);
// Checks for walls either side of the player
m_HitLhsWall = Physics.Raycast(transform.position, m_Orientation.right, out m_LhsWall, m_WallCheckDistance, m_GroundMask);
m_HitRhsWall = Physics.Raycast(transform.position, -m_Orientation.right, out m_RhsWall, m_WallCheckDistance, m_GroundMask);
// Checks the player is far enough of the ground to start wall running
m_IsFarEnoughOffGroundToWallRide = m_GroundHit.distance > m_DistanceOfFloorToWallRide;
// Updates the state of the user input
UpdateInput();
@@ -112,24 +144,6 @@ public class PlayerMovement : MonoBehaviour
m_SpeedDisplay.text = "Speed: " + m_Body.velocity.magnitude.ToString("0.00");
}
// Updates basic movement and player jumping
private void UpdatePlayerPosition()
{
// Sliding has its own movement code so the force being applied here is not needed
if (m_Sliding == false)
{
// Adds the force to the rigid body
m_Body.AddForce(m_MoveDir.normalized * m_MoveSpeed * m_Body.mass * 10.0f, ForceMode.Force);
}
// Jumps if the jump key has been pressed
if (m_JumpKeyPressed)
{
// The jump function stops jumping if not grounded so no check is needed here
Jump();
}
}
// Handles the logic for starting to slide
private void StartSlide()
{
@@ -156,37 +170,8 @@ public class PlayerMovement : MonoBehaviour
// Function to manage the sliding of the player
private void UpdateSlidingState()
{
// Works out wether the player's velocity is high enough to slide
Vector3 vel = m_Body.velocity;
bool canSlide =
!(
Mathf.Abs(vel.x) < m_SlideRequiredSpeed &&
Mathf.Abs(vel.z) < m_SlideRequiredSpeed
) || true;
// Checks wether the key state is valid for starting a slide
if (m_SlidingKeyPressed == true && m_Sliding == false)
{
// Checks player is moving in a direction
if (canSlide)
{
m_Sliding = true; // Updates the sliding state
StartSlide();
}
}
// Checks wether the player has stopped a slide or
// the player sliding if they are moving too slow
else if ((m_SlidingKeyPressed == false && m_Sliding == true) || (canSlide == false && m_Sliding == true))
{
m_Sliding = false; // Updates the sliding state
StopSlide();
}
// Correctly applies force on slopes
if (m_Sliding && m_OnSlope)
if (m_OnSlope)
{
Vector3 slopeDir = m_SlopeHit.normal;
slopeDir.y = 0.0f - slopeDir.y;
@@ -198,6 +183,25 @@ public class PlayerMovement : MonoBehaviour
{
m_Body.AddForce(m_MoveDir.normalized * m_SlideSpeed * m_Body.mass * 10, ForceMode.Force);
}
//m_Body.AddForce(Vector3.down * m_Body.mass * 5.0f, ForceMode.Impulse);
}
private void UpdateWallRunState()
{
// Calculates the foward direction of the wall
Vector3 normal = m_HitRhsWall ? m_RhsWall.normal : m_LhsWall.normal;
Vector3 foward = Vector3.Cross(normal, transform.up);
// Flips the foward direction if facing the other direction
if ((m_Orientation.forward - foward).magnitude > (m_Orientation.forward - -foward).magnitude)
{ foward = -foward; }
// Applies the wall running force to the player
m_Body.AddForce(foward * m_WallRunSpeed * m_Body.mass * 10.0f, ForceMode.Force);
// Removes any vertical velocity the player may have
//m_Body.velocity = new Vector3(m_Body.velocity.x, 0.0f, m_Body.velocity.z);
}
// Function to make the player jump
@@ -213,30 +217,110 @@ public class PlayerMovement : MonoBehaviour
}
}
private void UpdatePlayerState()
{
// Stores previous state
PlayerState previous = m_State;
// Works out wether the player's velocity is high enough to slide
Vector3 vel = m_Body.velocity;
bool canSlide =
!(
Mathf.Abs(vel.x) < m_SlideRequiredSpeed &&
Mathf.Abs(vel.z) < m_SlideRequiredSpeed
);
// Checks if the player is in the wall running state
if (m_HitLhsWall || m_HitRhsWall)
{ m_State = PlayerState.WALL_RUNNING; }
// Checks if the player is in the wall riding state
else if (m_SlidingKeyPressed && (canSlide || m_OnSlope) && m_Grounded)
{ m_State = PlayerState.SLIDING; }
// Defaults to ruuning
else { m_State = PlayerState.RUNNING; }
// Exits early if the state has not changed
if (previous == m_State)
{ return; }
// Calls exit function of old state
switch (previous)
{
case PlayerState.SLIDING:
StopSlide();
break;
default:
break;
}
// Calls entry function of new state
switch (m_State)
{
case PlayerState.SLIDING:
StartSlide();
break;
default:
break;
}
}
// Fixed Update is called once per physics update
private void FixedUpdate()
{
// Works out the new state of the player
UpdatePlayerState();
// Calculates the movement direction
m_MoveDir = (m_Orientation.forward * m_Input.y) + (m_Orientation.right * m_Input.x);
// Does additional calculations on the movement direction if on a slope
//
if (m_OnSlope)
{
// Calculates better move direction for sliding
m_MoveDir = Vector3.ProjectOnPlane(m_MoveDir, m_SlopeHit.normal).normalized;
m_Body.useGravity = false; // Disables gravity on slopes
}
else
// Runs correct update function depending on player state
switch (m_State)
{
m_Body.useGravity = true; // Renables gravity to stop errors
case PlayerState.RUNNING:
// Adds the force to the rigid body
m_Body.AddForce(m_MoveDir.normalized * m_MoveSpeed * m_Body.mass * 10.0f, ForceMode.Force);
// Stops player sliding slopes when they don't want to
if (m_OnSlope)
{ m_Body.useGravity = false; }
// Non-Slope running requires gravity on
else
{ m_Body.useGravity = true; }
break;
case PlayerState.SLIDING:
m_Body.useGravity = false; // Disables gravity on slopes
// Calls correct update function
UpdateSlidingState();
break;
case PlayerState.WALL_RUNNING:
// Calls correct update function
UpdateWallRunState();
m_Body.useGravity = false; // Disables gravity on walls to stop the player sliding off them
break;
}
// Updates the player sliding state
UpdateSlidingState();
// Updates the position of the player
UpdatePlayerPosition();
// Calls the Jump function if the user has pressed jump
// No grounded checks needed as Jump() function does that internally
if (m_JumpKeyPressed)
{
Jump();
}
// Updates the counter for slide boost updates left
m_TicksOfSlideBoostLeft = (int)Mathf.Clamp(m_TicksOfSlideBoostLeft - 1, 0, Mathf.Infinity);