2D Wall Jumping Almost Working. How to Increase X-Axis Jump Distance Away From Wall?

So I almost have wall jumping working for my 2D rigibody. I’ve been searching through posts here to see if I’ll find something similar to my question. Though what I’ve tried has not worked so far such as AddForce and transform.right.

BTI_022024_Left
BTI_022024_Right

For context:
I’m using a TileMap with its own Collider2D, Rigibody, and Composite Collider 2D for the ground, walls, and ceilings. The player game object is using a rigibody 2D with a physics material 2D (prevent friction / getting stuck on walls) and the recent player input system. The player rigibody2D also has 3 scripts attached for player controls, touching directions, and animation strings. The touching directions script uses a CapsuleCollider2D, ContactFilter2D, and 3 RayCastHit2D arrays for ground, walls, and ceilings detection. The player controller script is of course using the player input system events function calls for player controls.

I’ve been struggling to figure out how to get an increase on the player’s x axis distance from wall while wall jumping. The y axis distance does increase of course, but this does not seem to affect the x-axis whatsoever. So any ideas or assistance would be greatly appreciated!

Here is some of my code from the Player controller(hope it is simple to understand):

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        touchingDirections = GetComponent<TouchingDirections>();
    }

//How Player Moves
    private void FixedUpdate()
    {
        rb.velocity = new Vector2(moveInput.x * CurrentMoveSpeed, rb.velocity.y);
        animator.SetFloat(AnimationStrings.yVelocity, rb.velocity.y);
        WallSlide();
    }

    public void OnMove(InputAction.CallbackContext context)
    {
        moveInput = context.ReadValue<Vector2>();

        IsMoving = moveInput != Vector2.zero;

        SetFacingDirection(moveInput);
    }

    private void SetFacingDirection(Vector2 moveInput)
    {
        if(moveInput.x > 0 && !IsFacingRight)
        {
            IsFacingRight = true;
        }
        else if(moveInput.x < 0 && IsFacingRight)
        {
            IsFacingRight = false;
        }
    }


//Jump + Wall Jump    
public void OnJump(InputAction.CallbackContext context)
    {
        //TODO check if alive as well
        if(context.started && touchingDirections.IsGrounded)// || (!touchingDirections.IsGrounded && touchingDirections.IsOnWall)) 
        {
            //Either the trigger is set or not; no need for true/false
            animator.SetTrigger(AnimationStrings.jump);
            rb.velocity = new Vector2(rb.velocity.x, jumpImpulse);
        }

        //Wall Jump
        if (context.performed && (!touchingDirections.IsGrounded && touchingDirections.IsOnWall && isWallSliding))
        {

          //Why does the player barely jump away from the wall!!!!???
            rb.velocity = new Vector2(wallJumpingDirection * wallJumpingPower.x, jumpImpulse);
            //rb.AddForce(transform.right * 20000f, ForceMode2D.Impulse);
            //rb.velocity = new Vector2(rb.velocity.x + 0.25f * wallJumpingPower.y, jumpImpulse);

            if (transform.localScale.x != wallJumpingDirection)
            {
                Vector2 localScale = transform.localScale;
                localScale.x *= -1f;
                transform.localScale = localScale;
                _isFacingRight = !_isFacingRight;
            }
        }

        //Fix facing direction immediately after wall jumping while player is moving
        if((moveInput != Vector2.zero) && (!touchingDirections.IsGrounded && !touchingDirections.IsOnWall && !isWallSliding))
        {
            if(transform.localScale.x == wallJumpingDirection)
            {
                SetFacingDirection(moveInput);
            }
        }

        //For small jumps
        if(context.canceled && rb.velocity.y > 0f)
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f);
        }
    }

    private void WallSlide()
    {
        if(touchingDirections.IsOnWall && !touchingDirections.IsGrounded && (moveInput.x != 0))
        {
            isWallSliding = true;
            rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -wallSlidingSpeed, float.MaxValue));
            wallJumpingDirection = -transform.localScale.x;
        }
        else
        {
            isWallSliding = false;
        }
    }

Code from the touching direction scripts if this helps:

    public ContactFilter2D castFilter;
    public float groundDistance = 0.05f;
    public float wallDistance = 0.2f;
    public float ceilingDistance = 0.05f;

    CapsuleCollider2D touchingCol;
    Animator animator;

    RaycastHit2D[] groundHits = new RaycastHit2D[5];
    RaycastHit2D[] wallHits = new RaycastHit2D[5];
    RaycastHit2D[] ceilingHits = new RaycastHit2D[5];

//I do flip the local scale in player controller script, but this sort of, occasionally //causes a bug at the top of a wall when wall jumping
    private Vector2 wallCheckDirection => gameObject.transform.localScale.x > 0 ? Vector2.right : Vector2.left;

    [SerializeField]
    private bool _isGrounded;

    public bool IsGrounded 
    { 
        get 
        { 
            return _isGrounded;
        } 
        private set 
        { 
            _isGrounded = value;
            animator.SetBool(AnimationStrings.isGrounded, value);
        } 
    }

    private void Awake()
    {
        //rb = GetComponent<Rigidbody2D>();
        touchingCol = GetComponent<CapsuleCollider2D>();
        animator = GetComponent<Animator>();
    }

    void FixedUpdate()
    {               //vvvv Returns an int
        IsGrounded = touchingCol.Cast(Vector2.down, castFilter, groundHits, groundDistance) > 0;
        IsOnWall = touchingCol.Cast(wallCheckDirection, castFilter, wallHits, wallDistance) > 0;
        IsOnCeiling = touchingCol.Cast(Vector2.up, castFilter, ceilingHits, ceilingDistance) > 0;
    }

In your FixedUpdate(), the player velocity is always set to Vector2(moveInput.x * CurrentMoveSpeed, rb.velocity.y); Even if the wall jump changes the x velocity to move away from the wall, the x velocity will immediately change back to the player’s input direction on the next frame.

You may need to implement air acceleration/deceleration or have some arbitrary lockout time after a wall jump where you ignore the player’s x-input and just let the wall jump velocity control the movement.

Yep! This was the case. I fixed this by adding a coroutine, which is like a temporary update method. Pretty much 99% of my code for wall jumping went into the coroutine, and I added another method to call this coroutine. I also used a bool and a float to arbitrarily lock the player movement to allow the rigibody’s velocity to be controlled by the wall jumping velocity. I used WaitForSeconds in the coroutine for locking player movement.

Thanks for your answer/input/feedback.