Hello, I am currently working on a 2D platform game and have made quite a lot of progress so far, I can make my character move, jump, double jump and teleport. I want to make my character able to wall jump, in other words if there are 2 walls jump between them to move up. I have tried to do it here and I have my cahracter sticking to the wall and sliding down it slowly, however you then cant move away from the wall or jump to another one, could someone point me in the right direction please? Thanks!
player Controller Script
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(PlayerPhysics))]
public class PlayerController : MonoBehaviour {
//Player handling
public float gravity = 40;
public float speed = 20;
public float acceleration = 30;
public float jumpHeight = 12;
private bool wallHolding;
private float currentSpeed;
private float targetSpeed;
private Vector2 amountToMove;
private PlayerPhysics playerPhysics;
const int MAX_JUMPS = 2;
int jumpsLeft = MAX_JUMPS;
// Use this for initialization
void Start () {
playerPhysics = GetComponent<PlayerPhysics> ();
}
// Update is called once per frame
void Update () {
if (playerPhysics.movementStopped) {
targetSpeed = 0;
currentSpeed = 0;
}
//Input
targetSpeed = Input.GetAxisRaw ("Horizontal") * speed;
currentSpeed = IncrementTowards (currentSpeed, targetSpeed, acceleration);
if (playerPhysics.grounded) {
jumpsLeft = MAX_JUMPS;
amountToMove.y = 0;
}
//jump
if (jumpsLeft > 0 && Input.GetButtonDown ("Jump")) {
amountToMove.y = jumpHeight;
jumpsLeft -= 1;
} else {
if (!wallHolding) {
if (playerPhysics.canWallHold) {
wallHolding = true;
}
}
}
amountToMove.x = currentSpeed;
if (wallHolding) {
amountToMove.x = 0;
if (Input.GetAxisRaw ("Vertical") != -1) {
amountToMove.y = 0;
}
}
amountToMove.y -= gravity * Time.deltaTime;
playerPhysics.Move (amountToMove * Time.deltaTime);
}
//Increae n towards target by speed
private float IncrementTowards(float n, float target, float a) {
if (n == target) {
return n;
}
else {
float dir = Mathf.Sign (target - n); //must n be increased or decreased to get closer to target
n += speed * Time.deltaTime * dir;
return (dir == Mathf.Sign (target - n)) ? n : target; //if n has now passed target then return target, otherwise return n
}
}
}
Player Physics Script
using UnityEngine;
using System.Collections;
[RequireComponent (typeof(BoxCollider))]
public class PlayerPhysics : MonoBehaviour {
public LayerMask CollisionMask;
private BoxCollider collider;
private Vector3 s;
private Vector3 c;
private float skin = .005f;
[HideInInspector]
public bool grounded;
[HideInInspector]
public bool movementStopped;
[HideInInspector]
public bool canWallHold;
Ray ray;
RaycastHit hit;
void Start() {
collider = GetComponent<BoxCollider> ();
s = collider.size;
c = collider.center;
}
public void Move(Vector2 moveAmount) {
float deltaY = moveAmount.y;
float deltaX = moveAmount.x;
Vector2 p = transform.position;
//Check Collisions Up and Down
grounded = false;
for (int i = 0; i<3; i ++) {
float dir = Mathf.Sign(deltaY);
float x = (p.x + c.x - s.x / 2) + s.x / 2 * i; //left, centre and right part of collider
float y = p.y + c.y + s.y / 2 * dir; //bottom of collider
ray = new Ray (new Vector2(x,y), new Vector2(0,dir));
//Debug.DrawRay(ray.origin, ray.direction);
if (Physics.Raycast(ray, out hit, Mathf.Abs(deltaY)+ skin, CollisionMask)){
//Get Distance between player and ground
float dst = Vector3.Distance (ray.origin, hit.point);
// stop players downwards movement when coming with skin distance of collider
if (dst > skin) {
deltaY = -dst - skin * dir;
}
else {
deltaY = 0;
}
grounded = true;
break;
}
}
//Check Collisions Left And Right
movementStopped = false;
canWallHold = false;
if (deltaX != 0) {
for (int i = 0; i<3; i ++) {
float dir = Mathf.Sign (deltaX);
float x = p.x + c.x + s.x / 2 * dir; //left, centre and right part of collider
float y = p.y + c.y - s.y / 2 + s.y / 2 * i; //bottom of collider
ray = new Ray (new Vector2 (x, y), new Vector2 (dir, 0));
//Debug.DrawRay(ray.origin, ray.direction);
if (Physics.Raycast (ray, out hit, Mathf.Abs (deltaX) + skin, CollisionMask)) {
if (hit.collider.tag == "Wall Jump") {
canWallHold = true;
}
//Get Distance between player and ground
float dst = Vector3.Distance (ray.origin, hit.point);
// stop players downwards movement when coming with skin distance of collider
if (dst > skin) {
deltaX = -dst - skin * dir;
} else {
deltaX = 0;
}
movementStopped = true;
break;
}
}
}
if (!grounded && !movementStopped) {
Vector3 playerDir = new Vector3 (deltaX, deltaY);
Vector3 o = new Vector3 (p.x + c.x + s.x / 2 * Mathf.Sign (deltaX), p.y + c.y + s.y / 2 * Mathf.Sign (deltaY));
ray = new Ray (o, playerDir.normalized);
if (Physics.Raycast (ray, Mathf.Sqrt (deltaX * deltaX + deltaY * deltaY), CollisionMask)) {
grounded = true;
deltaY = 0;
}
}
Vector2 finalTransform = new Vector2(deltaX,deltaY);
transform.Translate (finalTransform);
}
}