I’m a beginner and I am stumped. Raycasts work very good but you have to hug the wall for it to work. I have also tried OnCollisionEnter/OnCollisionStay and it doesn’t work very good. Any suggestions
? (some things are useless since i haven’t cleaned up the code. Hope it doesn’t complicate too much.
{
[Header("Wallrunning")]
public LayerMask whatIsWall;
public LayerMask whatIsGround;
public float wallRunForce;
public float wallJumpUpForce;
public float wallJumpSideForce;
public float wallClimbSpeed;
public Vector3 wallNormal;
public Vector3 wallForward;
[Header("Input")]
public KeyCode jumpKey = KeyCode.Space;
private float horizontalInput;
private float verticalInput;
[Header("Detection")]
public float wallCheckDistance;
public float minJumpHeight;
private RaycastHit leftWallhit;
private RaycastHit rightWallhit;
public bool wallLeft;
public 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 Transform CameraHolder;
public PlayerCam cam;
public PlayerMovement pm;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
pm = GetComponent<PlayerMovement>();
}
private void Update()
{
CheckForWall();
StateMachine();
}
private void FixedUpdate()
{
if (pm.wallrunning)
WallRunningMovement();
}
private void CheckForWall()
{
wallRight = Physics.Raycast(transform.position, orientation.right, out rightWallhit, wallCheckDistance, whatIsWall) ||
Physics.Raycast(transform.position, orientation.right - orientation.forward, out rightWallhit, wallCheckDistance, whatIsWall) ||
Physics.Raycast(transform.position, orientation.right - -orientation.forward, out rightWallhit, wallCheckDistance, whatIsWall);
//horizontal right
Debug.DrawRay(transform.position, orientation.right, Color.red);
//diag down right
Debug.DrawRay(transform.position, orientation.right - orientation.forward, Color.green);
//diad up right
Debug.DrawRay(transform.position, (orientation.right - -orientation.forward), Color.purple);
wallLeft = Physics.Raycast(transform.position, -orientation.right, out leftWallhit, wallCheckDistance, whatIsWall) ||
Physics.Raycast(transform.position, -orientation.right + -orientation.forward, out leftWallhit, wallCheckDistance, whatIsWall) ||
Physics.Raycast(transform.position, -orientation.right - -orientation.forward, out leftWallhit, wallCheckDistance, whatIsWall);
//horiz left
Debug.DrawRay(transform.position, -orientation.right, Color.blue);
//diag down left
Debug.DrawRay(transform.position, -orientation.right + -orientation.forward, Color.yellow);
//diag up left
Debug.DrawRay(transform.position, -orientation.right - -orientation.forward, Color.brown);
}
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");
// State 1 - Wallrunning
if ((wallLeft || wallRight) && AboveGround() && !exitingWall)
{
if (!pm.wallrunning)
StartWallRun();
// wall jump
if (Input.GetKeyDown(jumpKey)) WallJump();
}
// State 2 - Exiting
else if (exitingWall)
{
if (pm.wallrunning)
StopWallRun();
if (exitWallTimer > 0)
exitWallTimer -= Time.deltaTime;
if (exitWallTimer <= 0)
exitingWall = false;
}
// State 3 - None
else
{
if (pm.wallrunning)
StopWallRun();
}
}
private void OnCollisionEnter(Collision collision)
{
foreach (ContactPoint contact in collision.contacts)
{
Debug.DrawRay(contact.point, contact.normal, Color.red, 2.0f);
}
}
public void OnCollisionStay(Collision collision)
{
if (wallLeft || wallRight && pm.wallrunning)
{
//upward and downwards wallrun
if (collision.gameObject.tag == "UpWr")
{
rb.linearVelocity = new Vector3(rb.linearVelocity.x, wallClimbSpeed, rb.linearVelocity.z);
}
if (collision.gameObject.tag == "DownWr")
{
rb.linearVelocity = new Vector3(rb.linearVelocity.x, -wallClimbSpeed, rb.linearVelocity.z);
}
}
foreach (ContactPoint contact in collision.contacts)
{
Debug.DrawRay(contact.point, contact.normal, Color.white, 2.0f);
}
}
private void StartWallRun()
{
pm.wallrunning = true;
rb.linearVelocity = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z);
// apply camera effects
cam.DoFov(90f);
if (wallLeft) cam.DoTilt(-5f);
if (wallRight) cam.DoTilt(5f);
}
public void WallRunningMovement()
{
rb.useGravity = false;
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);
// 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()
{
pm.wallrunning = false;
// reset camera effects
cam.DoFov(80f);
cam.DoTilt(0f);
}
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 linearVelocity and add force
rb.linearVelocity = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z);
rb.AddForce(forceToApply, ForceMode.Impulse);
}
}