Collision Code Question - Boolean Problem ?

Hi,
I have the following segment of code that is applied to my player, in the scene the player object sits between two walls whilst I’m testing the functionality out. When you press the up arrow, the object should move forward and when it hits a wall, it stops, the ‘move forward’ code is then disabled to stop the object from passing through the wall ( yes, I know I could use Rigidbodies ! :slight_smile: ), unfortunately, though I can’t seem to enable it again once I move away from the wall, same for down arrow, I get to use the code once for each direction and that is it ! :frowning:

So, question is, how do I re-enable my ‘movement’ properly once I have moved away from any wall obstacle ?

I will eventually add left and right movement functionality too.

    void Update()
    {
        // Movement - Forward
        if (Input.GetKey(KeyCode.UpArrow))
        {
            canMoveF = true;
        }

        if (canMoveF)
        {
            RaycastHit hitF; // RaycastHit returns information about ray hitF
            Ray rayF = new Ray(transform.position, transform.forward); // Define Ray rayF

            // Draw ray ( editor view only )
            Vector3 forward = transform.TransformDirection(Vector3.forward) * lineSize;
            Debug.DrawRay(transform.position, forward, Color.green);

            // Move forward
            transform.Translate(Vector3.forward * movementSpeed * Time.deltaTime);

            // Has ray 'hit' anything, if so, store in hitF, ray length from lineSize
            if (Physics.Raycast(rayF, out hitF, lineSize))
            {
                // Have we collided with a wall
                if (hitF.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Front!");
                    canMoveF = false; // Stop forward movement
                }
            }
        }

        // Movement - Backward
        if (Input.GetKey(KeyCode.DownArrow))
        {
            canMoveB = true;
        }

        if (canMoveB)
        {
            RaycastHit hitB; // RaycastHit returns information about ray hitB
            Ray rayB = new Ray(transform.position, -transform.forward); // Define Ray rayB

            // Draw ray ( editor view only )
            Vector3 backward = transform.TransformDirection(Vector3.back) * lineSize;
            Debug.DrawRay(transform.position, backward, Color.green);

            // Move backward
            transform.Translate(Vector3.back * movementSpeed * Time.deltaTime);

            // Has ray 'hit' anything, if so, store in hitB, ray length from lineSize
            if (Physics.Raycast(rayB, out hitB, lineSize))
            {
                // Have we collided with a wall
                if (hitB.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Back!");
                    canMoveB = false; // Stop backward movement
                }
            }
        }
    }
if(canMoveF)
{
//your code
} else
{
    //everything you want to happen when !canMoveF...
}

You could maybe use a while loop here, and while you are within a certain distance of the wall, canMoveF = false; and change it to true when that distance reaches your required amount

1 Like

You only ever set rayDirectionF back to false while you’re within the “moving forward” section of the code. And you’ll never get into the “moving forward” section of the code as long as rayDirectionF is false. You could set rayDirectionF to false when you move backwards and rayDirectionB to false when you move forward.

You are kind of doing things backwards. In most movement code, you’d check to see if you can move before moving. That way you don’t have to “remember” from frame to frame whether you hit a wall last frame; you can just check each frame, and you won’t have as many issues of getting “stuck” in a bad state. Additionally, with your method, if you have a varying framerate, your player could easily go through the wall if they cross the boundary on the wrong frame. And if you have an environment where the walls can change (opening doors, moving platforms, etc etc), the player will get stuck on a wall that used to exist, even with the above fix.

But…why wouldn’t you do that? It would solve all the above problems (and more) and would take like 3-4 lines of code.

1 Like

Thanks, @ItzChris92 @StarManta

I’m sure my code is super convoluted, but I figured out a solution, works well enough for test purposes.

using UnityEngine;

// Movement     |   Key Control + Rb + Slide
// Rigidbody    |   Yes

public enum DIRECTION { FORWARD, BACKWARD, LEFT, RIGHT }

public class MovementRbSlide : MonoBehaviour
{
    [Header("Movement Speed")]
    public float movementSpeed = 10f;

    [Header("Raycast Linesize")]
    public float raycastLinesize = 0.515f;

    [Header("Movement Direction")]
    [SerializeField]
    private DIRECTION movementDirection = DIRECTION.FORWARD;

    [Header("Logic Booleans")]
    [SerializeField]
    private bool canMove;
    [SerializeField]
    private bool moving;

    [Header("Keyboard Booleans")]
    [SerializeField]
    private bool keyU;
    [SerializeField]
    private bool keyD;
    [SerializeField]
    private bool keyL;
    [SerializeField]
    private bool keyR;

    private Rigidbody playerBody;

    private Vector3 pos;

    void Start()
    {
        playerBody = GetComponent<Rigidbody>();

        canMove = true;
        moving = false;

        keyU = true;
        keyD = true;
        keyL = true;
        keyR = true;
    }

    void FixedUpdate()
    {
        if (canMove)
        {
            // Raycast to check if we have hit obstacle at the front of player
            RaycastHit hitF;
            Ray rayF = new Ray(transform.position, transform.forward);
            Vector3 forward = transform.TransformDirection(Vector3.forward) * raycastLinesize;
            Debug.DrawRay(transform.position, forward, Color.green);
            if (Physics.Raycast(rayF, out hitF, raycastLinesize))
            {
                if (hitF.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Front!");
                    keyU = false;
                }
            }
            else
            {
                keyU = true;
            }

            // Raycast to check if we have hit obstacle at the back of player
            RaycastHit hitB;
            Ray rayB = new Ray(transform.position, -transform.forward);
            Vector3 backward = transform.TransformDirection(Vector3.back) * raycastLinesize;
            Debug.DrawRay(transform.position, backward, Color.green);
            if (Physics.Raycast(rayB, out hitB, raycastLinesize))
            {
                if (hitB.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Back!");
                    keyD = false;
                }
            }
            else
            {
                keyD = true;
            }

            // Raycast to check if we have hit obstacle to the right of player
            RaycastHit hitR;
            Ray rayR = new Ray(transform.position, transform.right);
            Vector3 right = transform.TransformDirection(Vector3.right) * raycastLinesize;
            Debug.DrawRay(transform.position, right, Color.green);
            if (Physics.Raycast(rayR, out hitR, raycastLinesize))
            {
                if (hitR.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Right!");
                    keyR = false;
                }
            }
            else
            {
                keyR = true;
            }

            // Raycast to check if we have hit obstacle to the left of player
            RaycastHit hitL;
            Ray rayL = new Ray(transform.position, -transform.right);
            Vector3 left = transform.TransformDirection(Vector3.left) * raycastLinesize;
            Debug.DrawRay(transform.position, left, Color.green);
            if (Physics.Raycast(rayL, out hitL, raycastLinesize))
            {
                if (hitL.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Left!");
                    keyL = false;
                }
            }
            else
            {
                keyL = true;
            }

            pos = transform.position;
            Move();
        }

        if (moving)
        {
            if (transform.position == pos)
            {
                moving = false;
                canMove = true;

                Move();
            }

            playerBody.MovePosition(transform.position + pos * movementSpeed * Time.fixedDeltaTime);
        }
    }

    private void Move()
    {
        // If KeyU True, UpArrow is enabled
        if (keyU)
        {
            if (Input.GetKey(KeyCode.UpArrow))
            {
                if (movementDirection != DIRECTION.FORWARD)
                {
                    movementDirection = DIRECTION.FORWARD;
                }
                else
                {
                    canMove = false;
                    moving = true;

                    pos = Vector3.forward;
                }
            }
        }

        // If KeyD True, DownArrow is enabled
        if (keyD)
        {
            if (Input.GetKey(KeyCode.DownArrow))
            {
                {
                    if (movementDirection != DIRECTION.BACKWARD)
                    {
                        movementDirection = DIRECTION.BACKWARD;
                    }
                    else
                    {
                        canMove = false;
                        moving = true;

                        pos = Vector3.back;
                    }
                }
            }
        }

        // If KeyL True, LeftArrow is enabled
        if (keyL)
        {
            if (Input.GetKey(KeyCode.LeftArrow))
            {
                {
                    if (movementDirection != DIRECTION.LEFT)
                    {
                        movementDirection = DIRECTION.LEFT;
                    }
                    else
                    {
                        canMove = false;
                        moving = true;

                        pos = Vector3.left;
                    }
                }
            }
        }

        // If KeyR True, RightArrow is enabled
        if (keyR)
        {
            if (Input.GetKey(KeyCode.RightArrow))
            {
                {
                    if (movementDirection != DIRECTION.RIGHT)
                    {
                        movementDirection = DIRECTION.RIGHT;
                    }
                    else
                    {
                        canMove = false;
                        moving = true;

                        pos = Vector3.right;
                    }
                }
            }
        }
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == ("Wall"))
        {
            moving = false;
            canMove = true;
        }
    }
}