2D: Smooth Wall jump

My intention is to make my character wall jump/climb/slide, I got the sliding part working fine, but if he jumps while wall sliding, he should “bounce” back to the wall, the problem is that I can’t balance the forces. In all tutorial I saw, it is simply a matter of detecting if the character is wall sliding, and if he is and he jumps, then you add a force oposite to the wall.

This is not working for me, because if I add enough force to make him jump, he goes way too fast and the player can barely see he jumped, he just sees that the character is now higher on the wall. If I add a smaller amount of force, it isn’t enough to make a considerable jump and the player would have to hit space a thousand times to make him go up a few centimeters on the wall.

Any help is appreciated, I already tried a lot of things, even tried to freeze the controls, set gravity scale to 0 and make the character fo to the right points using MoveTowards, that is how desperate I am.

I’m also really new to Unity so I might be missing something really simple.

Here is a gif showing the character’s behavior: Imgur: The magic of the Internet

And here are the relevant parts of my character’s script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TheBot : MonoBehaviour {

	public float speed;
	public int jumpForce;
	public Transform groundCheck;
	public Transform meleeCheck;
	public Transform bulletSpawner;
	public LayerMask layerGround;
	public float meleeCoolDown;
	public float meleeDamage;

	private Rigidbody2D body;
	private Animator anim;
	private Dash dashController;
	private Shooter shotController;
	private float unloadWaitingTime = 3;
	private float idleGunTime = 0;

	private bool facingRight = true;
	private bool onGround = true;
	private bool jumping = false;
	private bool attacking = false;
	private bool dead = false;
	private bool isGunLoaded = false;
	private bool isGunLoading = false;
	private bool isGunUnloading = false;
	private bool takingDamage = false;
	private bool dashing = false;
	private bool isWallSliding = false;
	private bool wallJumping = false;


	void Start () {
		body = GetComponent<Rigidbody2D>();
		anim = GetComponent<Animator>();
		dashController = GetComponent<Dash>();
		shotController = GetComponent<Shooter>();
	}
	

	void Update () {
		PlayAnimations();
		CheckIfGrounded();
		checkIfWallSliding();
		dashing = dashController.IsDashing();

		if (Input.GetButtonDown("Jump") && onGround  && !isGunLoading && !jumping && !takingDamage  && !isWallSliding){
			jumping = true;
		}

		if(Input.GetButtonDown("Jump") && !onGround  && !isGunLoading && !takingDamage && !wallJumping && isWallSliding){
			wallJumping = true;
		}
		if (Input.GetButtonDown("Melee") && !attacking && !isGunLoading){
			Attack();
		}
		if(Input.GetButtonDown("Ranged") && !attacking  && !isGunLoading && onGround){
			Shoot();
		}

		if(Input.GetButtonDown("Dash") && !attacking && !isGunLoading && onGround){
			dashController.DashTo(facingRight? Dash.RIGHT : Dash.LEFT);
		}


		if(isGunLoaded){
			idleGunTime += Time.deltaTime;
			if (idleGunTime >= unloadWaitingTime){
				UnloadGun();
			}
		}

	}

	void FixedUpdate(){
		if(!takingDamage){

			float move = Input.GetAxis("Horizontal");

			if (isWallSliding && !jumping){
				body.velocity = new Vector2(body.velocity.x, -0.7f);
			}
			
			if(!dashing){
				if(onGround){
					body.velocity = new Vector2(move * speed, body.velocity.y);
				} else {
					//if character is not on ground, reduce the speed so he doesn't jump too far away
					body.velocity = new Vector2(move * (speed * 0.7f), body.velocity.y);
				}
			}

			if((move < 0 && facingRight) || (move > 0 && !facingRight) ){
				Flip();
			}

			if (jumping){

				body.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse);

				if(Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.LeftArrow)){
					body.velocity = new Vector2(body.velocity.x, body.velocity.y*0.8f);
				}
				onGround = false;
				jumping = false;
			} 		

			if (wallJumping){
				body.velocity = new Vector2(jumpPushForce * (facingRight ? -1:1), jumpForce);
				wallJumping = false;
				//body.AddForce(new Vector2(move * speed, jumpForce), ForceMode2D.Impulse);
			}
		}
	}


	void CheckIfGrounded(){
		onGround = false;
		Collider2D[] collisionResults = new Collider2D[2];
		int objectsBeneath = Physics2D.OverlapBoxNonAlloc(groundCheck.position, new Vector2(0.9f, 0.3f), 0.0f, collisionResults, layerGround);
		for (int i=0; i <objectsBeneath; i++ ){
			if (!GameObject.ReferenceEquals(gameObject, collisionResults*.gameObject)){*
  •  		onGround = true;*
    
  •  	}*
    
  •  }*
    
  • }*

  • void checkIfWallSliding(){*

  •  if (!onGround){*
    
  •  	RaycastHit2D[] ray = new RaycastHit2D[1];*
    
  •  	int totalRayHits = Physics2D.LinecastNonAlloc(bulletSpawner.position, body.position, ray, 1 << LayerMask.NameToLayer("SolidGround"));*
    
  •  	bool wallFound = totalRayHits > 0 && ray[0].collider.gameObject.tag == "SolidGround";*
    
  •  	isWallSliding = wallFound && ( (facingRight && Input.GetKey(KeyCode.RightArrow)) ||  (!facingRight && Input.GetKey(KeyCode.LeftArrow))) ;*
    
  •  	if (isWallSliding) wallJumping = false;*
    
  •  } else {*
    
  •  	isWallSliding = false;*
    
  •  }*
    
  • }*

  • void Flip(){*

  •  facingRight = !facingRight;*
    
  •  transform.localScale = new Vector3( -transform.localScale.x, transform.localScale.y, transform.localScale.z);*
    
  • }*
    }

Hey man!

did you solve that problem?

I’m in the same situation as you are.

Can you share de solution, if you did solve that problem?

Thanks so much.