Unity Raycast Being Weird

Started by
6 comments, last by Ovicior 7 years, 11 months ago

I've been working on a 2D raycasting system, and have an odd glitch-like thing going on. When the rays fire off and collide with something, all of the rays work perfectly well except for one. This ray keeps pushing past the collider and, in turn, is constantly changing the player's y-values.

Can anyone see a fix?

3348630296886ffc4781eceeb97ffbd2.gif

Code:


using UnityEngine;
using System.Collections;

[RequireComponent(typeof(BoxCollider2D))]
public class Controller2D : MonoBehaviour
{

    public LayerMask collisionMask;

    const float skinWidth = .015f;
    public int horizontalRayCount = 4;
    public int verticalRayCount = 4;

    float horizontalRaySpacing;
    float verticalRaySpacing;

    BoxCollider2D collider;
    RaycastOrigins raycastOrigins;

    void Start()
    {
        collider = GetComponent<BoxCollider2D>();
        CalculateRaySpacing();
    }

    public void Move(Vector3 velocity)
    {
        UpdateRaycastOrigins();
        if (velocity.x != 0)
        {
            HorizontalCollisions(ref velocity);
        }
        if (velocity.y != 0)
        {
            VerticalCollisions(ref velocity);
        }

        transform.Translate(velocity);
    }

    void HorizontalCollisions(ref Vector3 velocity)
    {
        float directionX = Mathf.Sign(velocity.x);
        float rayLength = Mathf.Abs(velocity.x) + skinWidth;

        for (int i = 0; i < horizontalRayCount; i++)
        {
            Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight;
            rayOrigin += Vector2.up * (horizontalRaySpacing * i);
            RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.right * directionX, rayLength, collisionMask);

            Debug.DrawRay(rayOrigin, Vector2.right * directionX * rayLength, Color.red);

            if (hit)
            {
                velocity.x = (hit.distance - skinWidth) * directionX;
                rayLength = hit.distance;
            }
        }
    }

    void VerticalCollisions(ref Vector3 velocity)
    {
        float directionY = Mathf.Sign(velocity.y);
        float rayLength = Mathf.Abs(velocity.y) + skinWidth;

        for (int i = 0; i < verticalRayCount; i++)
        {
            Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;
            rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);
            RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);

            Debug.DrawRay(rayOrigin, Vector2.up * directionY * rayLength, Color.red);

            if (hit)
            {
                velocity.y = (hit.distance - skinWidth) * directionY;
                rayLength = hit.distance;
            }
        }
    }

    void UpdateRaycastOrigins()
    {
        Bounds bounds = collider.bounds;
        bounds.Expand(skinWidth * -2);

        raycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y);
        raycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y);
        raycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y);
        raycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y);
    }

    void CalculateRaySpacing()
    {
        Bounds bounds = collider.bounds;
        bounds.Expand(skinWidth * -2);

        horizontalRayCount = Mathf.Clamp(horizontalRayCount, 2, int.MaxValue);
        verticalRayCount = Mathf.Clamp(verticalRayCount, 2, int.MaxValue);

        horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);
        verticalRaySpacing = bounds.size.x / (verticalRayCount - 1);
    }

    struct RaycastOrigins
    {
        public Vector2 topLeft, topRight;
        public Vector2 bottomLeft, bottomRight;
    }

}
What will you make?
Advertisement

While I don't immediately see the error, you could try doing the Debug.Draw in different colors based on i to see if it's always the same ray that's messing up, and then Debug print values for that specific ray and see if anything becomes apparent.

In the VerticalCollisions I was slightly surprised to see velocity.x used, but I guess it makes sense for movement collision? (Although HorizontalCollisions doesn't do the equivalent.)

Hello to all my stalkers.

your'e probably experiencing an unusual case with the raycast caused by the corner.Try separating the box and the rectangular stage into separate pieces to see if that helps..

your'e probably experiencing an unusual case with the raycast caused by the corner.Try separating the box and the rectangular stage into separate pieces to see if that helps..

They both start separated, with the square at the top. The gravity causes the square to land on the rectangle.

What will you make?

While I don't immediately see the error, you could try doing the Debug.Draw in different colors based on i to see if it's always the same ray that's messing up, and then Debug print values for that specific ray and see if anything becomes apparent.

In the VerticalCollisions I was slightly surprised to see velocity.x used, but I guess it makes sense for movement collision? (Although HorizontalCollisions doesn't do the equivalent.)

Interestingly, the same ray is always changing when it shouldn't be. I changed the color and it still occurred. If the player falls from high enough, the rays doesn't seem to change its values. If the player lands close to the platform, the stray ray changes the value of the player by tiny amounts.

What will you make?

While I don't immediately see the error, you could try doing the Debug.Draw in different colors based on i to see if it's always the same ray that's messing up, and then Debug print values for that specific ray and see if anything becomes apparent.

In the VerticalCollisions I was slightly surprised to see velocity.x used, but I guess it makes sense for movement collision? (Although HorizontalCollisions doesn't do the equivalent.)

Interestingly, the same ray is always changing when it shouldn't be. I changed the color and it still occurred. If the player falls from high enough, the rays doesn't seem to change its values. If the player lands close to the platform, the stray ray changes the value of the player by tiny amounts.

FIGURED IT OUT!

Turns out the gravity was accumulating and forcing the ray down. Just had to set gravity to 0 in the update function.

What will you make?

If the rigidbody component is attached, you can turn off the gravity for the object there as well. (If not, you must be doing custom gravity)

If the rigidbody component is attached, you can turn off the gravity for the object there as well. (If not, you must be doing custom gravity)

No, I am not using the rigidbody. I have custom gravity.

Thanks anyway :D

What will you make?

This topic is closed to new replies.

Advertisement