Hi, I’m writing a randomized dungeon generating function, it assigns doors to a room[n], spawns a room[n+1] at the predetermined spot, then it uses the function (below) that calculates a number of colliders in a given area. If CollisionCount returns x > 1, it destroys the room[n+1] and removes the door and the corridor leading to it from room[n]
I decided to generate it inside FixedUpdate with each iteration of generating function happening each second, so that I can see debug.logs for each given iteration every second. As a result on the last picture I have the room from iteration_10 overlapping with the room from iteration_5, but (CollisionCount > 1) returns “false” for the rooms, I’ve even manually checked if Collider sizes and positions are wrong when an overlap happens, but they are always right. Is Physics2D.OverlapBoxAll working as intended here, why doesn’t it return all the colliders from the latter image?
OverlapBoxAll method uses halfextends and BoxSize is room’s collider.size, with your suggestion that makes OverlapBox too big to spawn anything.
Edit: wrong, Physics.OverlapBox uses halfextends and Physics2D.OverlapBoxAll uses actual sizes, I’ve gotta rewrite some parts of my code and see if it works now. Thank you for pointing out.
Edit_2: it works now, remarkable how such a silly mistake/overlook could cause hours of debugging.
Because otherwise there’s ton of dungeon generators already available on the store.
Your dungeon is on a grid. Each room has therefore grid coordinates spanning up a rectangle. You can simply create a Rect type and use its overlap tests to perform these operations. This will also be faster and avoids interference by other colliders that may happen to be in the scene.
It also has a downside of checking Overlaps only for other Rect type objects as I understand it, if I go with prefabs of arbitrary shape using physics seems to be the optimal solution.
Note that there’s Physics2D.OverlapArea where you can specify the two corners of a rectangle if it’s easier for you.
Also, know that the “All” suffixed queries return a new array of results. Whilst this might seem convenient, it’ll kill performance as it’ll throw those arrays to the garbage collector when you’ve done with them.
All the 2D physics queries allow you to pass in a List which it’ll automatically grow for you. You should create this once then reuse it for the lifetime of your game.
When you create a collider, it’s immediately available for querying, you don’t need to wait for the simulation step. Just ensure that if you’re using “Instantiate” that you pass the position/rotation/parent to that call. Don’t instantiate an object then immediatly change the Transform. Any Transform changes won’t be processed until the next simulation step which is why you should avoid and even never modify the Transform.
Changing the Rigidbody2D.position/.rotation is immediate btw.
There’s ten billion other examples out there, none of them using physics. As CodeSmile noted above, this is a well- and heavily-solved problem, but by all means help yourself if you want to try new mechanisms like physics.
Nope. A Rect intersection test is just comparing the four sides (corners) against each other, effectively just comparing two Vector2 against two other Vector2 (at most, quite often one test fails making the other test superfluous). So in all likelihood this going to be a lot faster and more memory efficient than running it through the entire physics simulation with colliders and what not.
Physics engines use fancy data structures to partition the world to help improve the performance of collision detection and casting functions. So basically when the physics wants to check for a collision it only needs to check it against other nearby objects.
This helps a lot, thank you. I don’t think these details about how physics2d stores data and collects garbage are part of unity documentation, I thought it creates and uses a single list for a specific method and rewrites it’s elements every time a method is called. Is there a place I can read more about it?
If I destroy an object with a collider and a rigidbody and run physics.overlapboxall during the same simulation step, will it return an empty list or a list with an object’s collider I’ve just destroyed?
That would only start to make a difference past a high number of objects / rectangles and spatially separated from one another. I wouldn’t expect a room generator to work with no more than a few hundred rooms though, so those few floating point comparisons are practically a no-cost operation.
I don’t think Rect will be more performant or easier to use for OP’s situation but it’s good that you’ve made them aware of it and that you’ve reminded me that it exists!
It returns 0 colliders if OverlapBoxAll is called after Destroy(). Yet I’m puzzled by your response, if Destroy() doesn’t happen until the end of the frame x_1, does it mean that absence of an object can only be detected at the beginning of the following frame x_2 as earliest as possible? I run the following code with Application.targetFrameRate = 1
void FixedUpdate()
{
Room = Instantiate(Rooms[0], new Vector3(0,0,0), Quaternion.identity);
Colliders = Physics2D.OverlapBoxAll(new Vector2(0,0), new Vector2(0,0), 0);
Debug.Log(Colliders.Length);
Destroy(Room);
Colliders = Physics2D.OverlapBoxAll(new Vector2(0,0), new Vector2(0,0), 0);
Debug.Log(Colliders.Length);
Time.timeScale = 0;
}
“Note that this function will allocate memory for the returned Collider2D array.”
… whereas the overload that allows you to pass in a list, Physics2D.OverlapBox says:
“The integer return value is the number of results written into the results list. The results list will be resized if it doesn’t contain enough elements to report all the results. This prevents memory from being allocated for results when the results list does not need to be resized, and improves garbage collection performance when the query is performed frequently.”
Create/use your own list in your script and just reuse it. Avoid the suffixed “All” calls where possible.
The object is not “fully” destroyed i.e. you can technically still refer to it but internally, all the componts are disabled/deactivated. In terms of 2D physics, the C# components are there but all the native back-end physics objects are gone so you cannot query them etc.
I think you’re getting distracted by details/definitions here. If you ask to destroy something, it’s “effectively” or “logically” gone and a lot of internal destruction happens immediately so just think of it like that.