0
\$\begingroup\$

I am currently making a 2d top down game in unity and have stumbled upon a problem with my raycast collision. I want my green player to stop moving when colliding with a wall, therefore i made my player object cast a ray in the direction it is moving. Its velocity is nullified when the distance to the collision point is equal to zero, or below. What seems to be the case is that the player object stops moving way to late and ends up overlapping the wall object. I tried to make an offset such that the player stopped a bit earlier, but it seems that the offset needs to differ depending on the side of the wall block. It even feels like the point at where the player stops is arbitrary and differs from time to time.

I would really like to know why this happens and what i can do to fix it. BTW, I would also really like to be able to change the players speed and still have it work.

Here are some pictures of my problem:

enter image description here enter image description here

The code i use for the player:

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

    [SerializeField]
    private float speed;

    Rigidbody2D body;
    bool justChangedDir;
    Vector2 moveDir;

    void Start()
    {
        body = GetComponent<Rigidbody2D>();
    }

    void MoveDirection()
    { 
        Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));

        if ((input.x != 0 && input.y == 0) || (input.x == 0 && input.y != 0))
            justChangedDir = false;

        if (moveDir.x != 0)
        {
            moveDir = new Vector2(input.x, 0);

            if (input.y != 0 && !justChangedDir)
            {
                moveDir = new Vector2(0, input.y);
                justChangedDir = true;
            }
        }

        else if (moveDir.y != 0)
        {
            moveDir = new Vector2(0, input.y);

            if (input.x != 0 && !justChangedDir)
            {
                moveDir = new Vector2(input.x, 0);
                justChangedDir = true;
            }
        }

        else
            moveDir = input;
    }

    void CheckCollision()
    {
        RaycastHit2D hit = new RaycastHit2D();

        if (moveDir.x != 0)
        {
            hit = Physics2D.Raycast(body.position, Vector2.right * moveDir.x, 1);


            Debug.DrawRay(body.position, Vector2.right * moveDir.x, Color.yellow);

        }

        else if (moveDir.y != 0)
        {
            hit = Physics2D.Raycast(body.position, Vector2.up * moveDir.y, 1);


            Debug.DrawRay(body.position, Vector2.up * moveDir.y, Color.yellow);
        }

        if (hit.collider != null && hit.distance <= 0.5 )
        {
            body.velocity = Vector2.zero;
        }
        else
        {
            body.velocity = moveDir * speed;
        }

    }

    // Update is called once per frame
    void Update()
    {
        MoveDirection();

        if (moveDir != Vector2.zero)
        {
            CheckCollision();
        }
        else
            body.velocity = Vector2.zero;
    }

}

Any help will be really appreciated :) Many thanks in advance!

Gusgus

\$\endgroup\$
4
\$\begingroup\$

This is because your raycast is from the center of the player to a length equal to speed. You're discounting the size of the player in this calculation.

hit = Physics2D.Raycast(body.position, Vector2.right * moveDir.x + player_radius, 1);

Where player_radius is the size of your player. It would be best to make this either a reference to the game object's transform's scale, the game object's collider's size, or a constant property (collider size is best, if you're using one).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.