- Home /
Collider to Screen Space: Determining if it's Within a Rect
The task is to determine whether any itty bitty part of an object's collider lay within a Rect on the screen.
Currently, my jury-rigged solution is to do a ray cast out from the center of the Rect to wherever on the 3D terrain it hits and for each object, find its Collider.ClosestPointOnBounds() to the hit point, project that point back to screen space, and then test if it lay within the rect. This works over 90% of the time, but there would be some cases where it would be off, like if it's an FPS and the ray hit a very distant or very close wall. In that case the ClosestPointOnBounds would appear more to the center of the object relative to the camera, and if the Rect's side was between this point and the collider's far edge, it wouldn't catch it. Not to mention, it seems clumsy to go casting a ray and doing all these 3D calculations just to bring it all back to 2D again.
I'd imagine that this is a relatively common task, and that there's a more clean-cut way to do it. Since Unity has already written a Collider.ClosestPointOnBounds method for 3D space, I would reckon it to be both simpler and less cpu-intensive to calculate it in 2D.
Thus my question is, how can one project an entire collider into 2D first, and then find the closest point of that 2D shape to a given point, or otherwise generally determine if the collider is at least partially within a bounding screen Rect?
I've been wondering about something similar here, I used a spherecast from my camera, but this has pretty much the same effect, when too close(or too far) the spherecast will react to objects outside of my 2D space.
$$anonymous$$ight be an idea to change the radius of the spherecast depending on the distance it travels before hitting something, but I'm not sure whether or not this is possible. Hope this or my question will be answered sometime, since they are essentially the same.
You may want to consider using Unity's built in functions for this, such as $$anonymous$$onobehaviour.OnBecameVisible and $$anonymous$$onobehaviour.OnBecameInvisible
Answer by ScroodgeM · Jul 19, 2012 at 06:41 PM
you are right that there's two main ways to compare 2d (screen) and 3d (mesh)
translate 2d to 3d and compare in 3d
translate 3d to 2d and compare in 2d
first about 2d - i'm not sure that comparing two rasterized 2d image to check it's intersects is less expensive then the next method.
second - 3d comparison. i think the easiest way is to make a simple collider (6 surfaces or 12 tris) that repeats camera's rect in 3d world. collider will look like camera's view area in scene view, but will be smaller a little - proportonal to your rect size. then make this collider as trigger and detect all collisions with it by script.
IMHO this is a very easy to calculate method, especially if you disable all unneeded collider interactions based on layers.
PS use a box collider instead of mesh if your camera is orthogonal