- Home /
2D: Why aren't my raycasts conforming to their origin points?
I've been testing some things with raycasts, but ran into an issue in which my raycasts don't appear to be adhering to their origin points. Basically, any movement alters where I think the raycasts should be starting.
Below is my simplified script; feel free to try this out in a new project (your character game object should have a box collider, and a rigidbody2D set to kinematic):
using UnityEngine;
public class RaycastTest: MonoBehaviour
{
public float speed = 5;
public float gravity = -10;
public LayerMask collisionMask; //Don't forget to set a layer to collide with
private BoxCollider2D boxCollider;
private Vector2 velocity;
private void Start()
{
boxCollider = GetComponent<BoxCollider2D>();
}
private void Update()
{
float input = Input.GetAxisRaw("Horizontal");
velocity.x = input * speed;
velocity.y += gravity * Time.deltaTime;
CollideVertically();
transform.Translate(velocity * Time.deltaTime);
}
private void CollideVertically()
{
Vector2 origin = new Vector2(boxCollider.bounds.center.x + (velocity.x * Time.deltaTime), boxCollider.bounds.center.y);
RaycastHit2D hit = Physics2D.Raycast(origin, Vector2.down, 1, collisionMask);
Debug.DrawRay(origin, Vector2.down, Color.red);
if (hit)
{
print("collided with ground");
}
}
}
CollideVertically()
draws a single ray downward from the center of the character's box collider (I use boxCollider.bounds.center
for this). I also add what I thought represents the "delta movement," or change in the character's velocity this frame, when setting the ray origin ( boxCollider.bounds.center.x + (velocity.x * time.deltaTime)
).
The problem is that the ray seems to lag behind the character when the character is moving left or right, and is displaced heavily on the y-axis when falling. If I set the ray origin using transform.position
this no longer occurs (keep in mind you still need to add the delta movement value to your x velocity), but only if I also call CollideVertically()
after transform.Translate(velocity * time.deltaTime)
in Update()
.
Am I doing something wrong? Is Debug.DrawRay
just showing me an inaccurate representation of my raycasts? Ideally I'd like my rays to follow my movement exactly, never altering their origin positions. I have read articles on game collisions that mention you're supposed to move first and then check for and resolve collisions. I appear to be doing the opposite here, and frankly I'm not sure if that's the right approach when using raycasts.
Here's an image showing what I mean (notice how the ray is NOT in the center of my collider in the game view on the right): https://imgur.com/a/oouf6lp
Also, you'll notice two red rays in the scene view; it's almost like the ray is "spazzing out" as it tries to get back to its intended position.
Here's another example with more rays (not included in the above script) that really shows why this might jeopardize my character's movement (I have gravity set to 0 here, and am moving left): https://imgur.com/a/ZoQI3HU
Answer by Dalsia · Jan 23, 2019 at 08:52 PM
UPDATE: Please ignore the old issue/solution. The way this was fixed was to check the box "Auto Sync Transforms" under Edit --> Project Settings --> Physics2D. This is unchecked by default, and made a SUBSTANTIAL difference in how my rays detected collisions.
Thank you very much to @sean244 and @dan_wipf for being patient and assisting me with this problem. It does indeed make more sense to call CollideVertically
after transform.Translate(velocity * time.deltaTime)
.
Here is an image of sean's settings that helped me figure out what was wrong with my project: https://www.dropbox.com/s/m4jk47k48jii5ga/Physics2D.jpg?dl=0
----- OLD ISSUE/SOLUTION (ignore) -----
So after trying so many different things, including running this code on slightly older versions of Unity, nothing seemed to work for me. However, after running this code in a new project on my old 2013 iMac that has a 2017 version of Unity installed on Windows (Bootcamp) the code ran flawlessly. In fact, changing my code by calling CollideVertically()
after transform.Translate(velocity * time.deltaTime)
produced even better results.
This is important because the raycasting results are affected by how each computer is displaying the rays. On my new PC, the one running the "bugged" code, the rays are not conforming to their origin points, and thus when moving the rays' hit data are not correct. This causes collisions to be inaccurate. When checking the hit points on the "working" version of my code on my old iMac, though, the rays exhibit near pixel perfect collision, which can be seen when allowing the character to fall and using Unity's frame-by-frame button to check where the ray collides with an object.
I assume this must be a hardware issue since the two computers I tested this on have totally different hardware. The most notable difference is the difference in GPUs; my iMac is running a NVIDIA GeForce 750m, and my new PC is running the NVIDIA RTX 2070. I have no idea how to fix this raycasting issue on my new PC, but I might as well post this here so others can know about it.
Glad you solved it. Be sure to checkout the platformer I made in Unity https://github.com/sean244/Braid-Clone It uses raycasting as well, in case you wanted another reference
Thanks for sharing! This will indeed be helpful as I attempt to create my own platformer and custom collision system.
Answer by dan_wipf · Jan 23, 2019 at 07:00 AM
well for your info, if you want to show the exact ray, then use debug.drawline(origin, hit.point)
@Dalsia EDIT:
Ok I guess I've found out, what the matter is with your code!
if you change the
print("collided with ground);
to
print("collided with: " + hit.transform.name);
it will show you, that you always collide with the players boxcollider2d.
now there are four things you can do,
you change the Layer of your player to Ignore RayCast
you change the RaycastHit origin point outside of the boxcollider2d
you disable the boxcollider2d + Raycast
or you look for collision detection without Raycast a thing.
might the first will be the easiest one!
I appreciate your response. Would you be able to elaborate on why you think that?
yes, i believe i can!
well i think it’s due to the executional order. if you make a ray before the final targetposition(origin) it will always take the origin of the last position(one frame behind) so if you put the ray after / at the end of your update section, the origin will be the position if the current cycle/frame
ok third one is not working because you relie on boxcoliders bb