- Home /
2D collision detection / box intersection WITHOUT physics
Hi all,
I'm using Unity 4.3 and C#.
I'm trying to write some 2D-only code to perform simple collision detection between non-physics-based sprites (i.e., no rigidbodies on anything). Obviously, because of the absence of rigidbodies, the OnCollision____2D()
methods will not ever be called. Moreover, I'm working at a small enough scope that I actually want every-frame fidelity, not the reduced simulation framerate of FixedUpdate()
.
My question is this: is there a good way to leverage built-in Unity mechanics (again, all game objects involved are Sprites) to do super-easy collision detection either with Collider2D
or some other built-in, or do I need to just write my own bounding box intersection test?
To be clear, I want to test the intersection of two bounding boxes, NOT a point with a bounding box. For now everything is axis-aligned, but that could definitely change.
Any ideas? Thanks!
I can think of a very fast one, but it´s only an aproximation (and that´s why this is only a coment). Calculate the bounding circle of both boxes and then just make the trivial raidus check. It should work pretty well with squares.
Thanks for the replies, but I'm not asking how to compute bounding box intersection. That's fairly straightforward (e.g., as described in Real-time Rendering).
I'm just wondering if there are built-ins in Unity that already do this and that work well with Unity concepts like Sprite, GameObject, Collider2D, etc.
I think you are asking your question based on a flawed assumption. You're leaving out a huge chunk of what makes it easy to develop in unity.
If you're leaving out the physics because it appears complicated, don't be scared off by it. It's hugely powerful, and it has all the simple things that you are already asking for. It will make your life much easier so use it than it will be to maintain your own collision functions. Your time is valuable. Don't reinvent the wheel.
If you're leaving it our because of efficiency, then you're forgetting the first rule of optimization. I'll almost guarantee you that your code for intersections will probably end up being slower than if you had just used the physics engine. That stuff has been optimized in such insane ways that you aren't going to come close to making anything that will beat it in speed. Build your game first. $$anonymous$$ake it efficient later, but only if it actually has efficiency problems.
Also, even if you don't want it to, the physics engine is such a huge part of unity that it's going to be running behind the scenes anyways, so you might as well use it to make your code easy to write and maintain.
You can still use transformations to move objects if you want to, but you can also add colliders on top of them to have objects interact with each other.
$$anonymous$$, I appreciate that there is a lot of wisdom in your general guidelines, but in this particular case the advice is too general and therefore not applicable.
First, I'm not scared of complexity and I'm not trying to reinvent the wheel. I understand the physics API well and have used it to great effect in the past. $$anonymous$$y question was precisely "is there a way to do this using Unity's tools so I don't have to reinvent things?" In the end the answer is "yes" and it's documented below.
Second, intersection testing a single pair of two-dimensional, axis-aligned bounding boxes requires four floating point comparisons and three boolean operations on the result. Hardly a performance concern. $$anonymous$$y avoidance of physics is not primarily for performance reasons either; this isn't about optimization more than it is about reducing complexity, which brings me to...
Third, in terms of maintainability, the simple code snippet in my self-answer below is far simpler, easier to create, easier to understand, and less prone to unexpected coupling and behavioral drift than attaching rigidbodies and colliders to my sprites just for the sake of one collision test.
Fourth, and most importantly: as I said, there is no physics in what I'm working on. There is no simulation of real-world properties. I don't want post-collision reactions or to prevent overlapping of my sprites. I want an intersection test and that's it. Using a physics engine here is a bit like taking a plane flight just for the free in-flight soda. It's counter-productive.
Answer by ohboyotero · Nov 26, 2013 at 09:32 PM
What follows is the best I could come up with. If anybody has a better suggestion, please weigh in!
Colliders have no easy way of intersection without using the physics system. However, it's easy to intersect Bounds objects with each other, and bounds are available from any renderer component. This code therefore does exactly what I needed:
if (object1.renderer.bounds.Intersects(object2.renderer.bounds)) {
// Do some stuff
}
I don't know the performance characteristics of getting renderer bounds, so it could be that this is not at all performant when scaled up to more objects.
Reasons I did not accept other suggestions
I do not want to use Physics. Yes, I realize I could change the fixed step interval, but I a) don't want the added overhead the system brings, and b) I don't want physics, period! There are many cases where you need collision detection and physics is inappropriate. I want to be able to move things to specific screen coordinates by their transforms, not by figuring out IK and then applying the correct forces to get them there. I don't want any objects affected by forces or collisions.
One thing, you do not necessarily need to use forces to use physics colliders. Depending on the use, you may be able to use kinematic triggers.
You can see the matrix of what collides with what to provide events here. It's fair enough that you do not want to use physics, it does feel like overkill, it's just worth checking anyway.
Anyhow, since it's been a while since you posted this, have you actually benchmarked your solution to see whether there is much of an overhead in getting the bounds? It'd be interesting to know.
The info you are providing is referencing the 3D physics engine in Unity.
Check out this answer for more info. The Collision $$anonymous$$atrix does not function the same way for the Box2D implementation in 4.3 Hopefully they change it in the future. Where it is now I find kinematic bodies worthless in 2D.
Yeah, the kinematic Rigidbody2D appears to behave just like having NO Rigidbody2D. I still use the setting for objects that use physics but then need to freeze in place. But if something is in motion, kinematic just doesn't add anything.
Thanks darthbator/Pyrian for that link. I have since run into that myself. REALLY strange that Unity would have a different collision matrix in 2D vs. 3D, and that it would make 2D collisions so useless.
It's especially annoying given that you're much more likely to want to do something non-physics-y in a 2D-style game, so it's all the more important that they give you working kinematic triggers.
Answer by Bunny83 · Nov 22, 2013 at 12:29 PM
The built in mechanics for collisions comes from the physics system. So without a Rigidbody(2D) you don't have any of that functionality. Unity used PhysX and the Rigidbody is the wrapper for it.
Keep in mind that you can change the Physics-timestep as you which. If you have enough processing power you could have 5000 PU/s (which would be around 100 physics steps per frame). So FixedUpdate does not run on a "reduced" rate, but on a fixed rate which ensures a certain amount of calls per second. If you want to ensure at least one physics update per frame you could do something like that:
//C#
void Update()
{
Time.fixedDeltaTime = Time.deltaTime/2.0f;
}
That would doing around 2 physics steps per frame.
I didn't use the 2D stuff yet (still using an older version of Unity), so i'm not sure if kinematic rigidbodies could cause collisions as well. If the Rigidbody2D is just a modified version of the usual RB probably not.
Other thsn that you might want to use Physics2D to do your own intersection checks.
Thanks for the answer!
I realize that Colliders are meant for use in the physics system, but the thing is I literally want NO physics here. I don't want forces, collision effects, or anything like that. So hooking in to the physics system seems like overkill. $$anonymous$$oreover, I want to be able to control all things involved via transform.position rather than adding forces.
Is there a way to "use physics" but turn collisions off (i.e., collisions will be detected, but the physics systems does not calculate the result)? Would I just use triggers ins$$anonymous$$d?
And if not, is there a way in Unity to easily get the bounds of two 2D game objects and do an intersection? I can't seem to find a reliable way to do this in 2D. Obviously writing an axis-aligned intersection method is cake, but I figure there are built-ins that I should be using.