WallRunning | FEP
Fri Apr 01 2022 08:45:06 GMT+0000 (Coordinated Universal Time)
Saved by @BiscuitTinx #c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallRunning : MonoBehaviour
{
[Header("Wallrunning")]
public LayerMask whatIsWall;
public LayerMask whatIsGround;
public float wallRunForce;
public float wallJumpUpForce;
public float wallJumpSideForce;
public float wallClimbSpeed;
public float maxWallRunTime;
private float wallRunTimer;
[Header("Input")]
public KeyCode jumpKey = KeyCode.Space;
public KeyCode upwardsRunKey = KeyCode.LeftShift;
public KeyCode downwardsRunKey = KeyCode.LeftControl;
private bool upwardsRunning;
private bool downwardsRunning;
private float horizontalInput;
private float verticalInput;
[Header("Detection")]
public float wallCheckDistance;
public float minJumpHeight;
private RaycastHit leftWallhit;
private RaycastHit rightWallhit;
private bool wallLeft;
private bool wallRight;
[Header("Exiting")]
private bool exitingWall;
public float exitWallTime;
private float exitWallTimer;
[Header("Gravity")]
public bool useGravity;
public float gravitycounterForce;
[Header("References")]
public Transform orientation;
public PlayerCam cam;
private Player player;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
player = GetComponent<Player>();
}
private void Update()
{
CheckForWall();
StateMachine();
}
private void FixedUpdate()
{
if (player.wallrunning)
{
WallRunningMovement();
}
}
private void CheckForWall()
{
// transform.position is the start point of the wall check
// orientation.right is the direction
// rightWallhit is to store hit info
// wallCheckDistance is the distance
wallRight = Physics.Raycast(transform.position, orientation.right, out rightWallhit, wallCheckDistance, whatIsWall);
wallLeft = Physics.Raycast(transform.position, -orientation.right, out leftWallhit, wallCheckDistance, whatIsWall);
}
private bool AboveGround()
{
return !Physics.Raycast(transform.position, Vector3.down, minJumpHeight, whatIsGround);
}
private void StateMachine()
{
// Getting Inputs
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
upwardsRunning = Input.GetKey(upwardsRunKey);
downwardsRunning = Input.GetKey(downwardsRunKey);
// state 1 - Wallrunning
if ((wallLeft || wallRight) && verticalInput > 0 && AboveGround() && !exitingWall)
{
if (!player.wallrunning)
{
StartWallRun();
}
// wallrun timer
if(wallRunTimer > 0)
{
wallRunTimer -= Time.deltaTime;
}
if(wallRunTimer <= 0 && player.wallrunning)
{
exitingWall = true;
exitWallTimer = exitWallTime;
}
// wall jump
if (Input.GetKeyDown(jumpKey))
{
WallJump();
}
}
// state 2 - Exiting
else if (exitingWall)
{
if (player.wallrunning)
{
StopWallRun();
}
if (exitWallTimer > 0)
{
exitWallTimer -= Time.deltaTime;
}
if (exitWallTimer <= 0)
{
exitingWall = false;
}
}
// State 3 - None
else
{
if (player.wallrunning)
{
StopWallRun();
}
}
}
private void StartWallRun()
{
player.wallrunning = true;
wallRunTimer = maxWallRunTime;
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
// apply camera effects
cam.DoFov(90f);
if (wallLeft)
{
cam.DoTilt(-5f);
}
if (wallRight)
{
cam.DoTilt(5f);
}
}
private void WallRunningMovement()
{
rb.useGravity = useGravity;
Vector3 wallNormal = wallRight ? rightWallhit.normal : leftWallhit.normal;
Vector3 wallForward = Vector3.Cross(wallNormal, transform.up);
if ((orientation.forward - wallForward).magnitude > (orientation.forward - -wallForward).magnitude)
{
wallForward = -wallForward;
}
// forward force
rb.AddForce(wallForward * wallRunForce, ForceMode.Force);
// upwards/downwards force
if (upwardsRunning)
{
rb.velocity = new Vector3(rb.velocity.x, wallClimbSpeed, rb.velocity.z);
}
if (downwardsRunning)
{
rb.velocity = new Vector3(rb.velocity.x, -wallClimbSpeed, rb.velocity.z);
}
// push to wall force
if (!(wallLeft && horizontalInput > 0) && (wallRight && horizontalInput < 0))
{
rb.AddForce(-wallNormal * 100, ForceMode.Force);
}
// weaken gravity
if (useGravity)
{
rb.AddForce(transform.up * gravitycounterForce, ForceMode.Force);
}
}
private void StopWallRun()
{
player.wallrunning = false;
// reset camera effects
cam.DoFov(80f);
cam.DoTilt(0);
}
private void WallJump()
{
// enter exiting wall state
exitingWall = true;
exitWallTimer = exitWallTime;
Vector3 wallNormal = wallRight ? rightWallhit.normal : leftWallhit.normal;
Vector3 forceToApply = transform.up * wallJumpUpForce + wallNormal * wallJumpSideForce;
// reset y velocity and add force
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(forceToApply, ForceMode.Impulse);
}
}



Comments