What are bounds?

I am almost new to scripting and facing trouble understanding the bounds and how they work. As far as I can understand is that they are like boundaries around a gameobject. But following are some questions that I am unable to understand:

  1. Do they completely cover/overlap the gameobject or just of some regular shape like circle, rectangle or square.
  2. Can we get a point on a bound and convert it to local space position?
  3. Can we use colliders as a bound and get a point on that collider and convert it to local space?

So GameObjectā€™s donā€™t have bounds.

Also, bounds can mean many thingsā€¦ like bounds of an array.

From the context though, it sounds like youā€™re talking about the Bounds struct:

And you can get them from things like:
Collider.bounds:

Mesh.bounds:

Renderer.bounds:

The bounds represent different things in each case.

But basically from the documentation:

So a ā€˜Boundsā€™ is an axis aligned bounding boxā€¦ AABB.

This means a box, or rectoid, in 3-spaceā€¦ that canā€™t be rotated. Itā€™s locked to the x/y/z axes.

In the case of a Collider.bounds. It is a AABB that fits around the collider. Think if you had a sphere colliderā€¦ the bounds would be a cube in which the sphere perfectly fits.

Mesh.bounds is the same thingā€¦ but around a mesh.

And Renderer.bounds is the same thingā€¦ but is the space made up of where rendering occurs for that object.

Itā€™s always larger than the thing itā€™s bounding.

The fact itā€™s axis aligned thoughā€¦ means that any rotation of oblong shaped things distort the bounding box a lot.

Bounding boxes are good to get very approximate relative locations of things. Since bounding box intersection is a very simple and fast calculation (relative to complex collision or similar)ā€¦ you can rule out things being anywhere near each other if their bounding boxes donā€™t intersect. Sure, they might not be intersecting even if the bounds are intersectingā€¦ but if the bounds donā€™t, then they certainly arenā€™t. Itā€™d be like saying ā€œcan Sally touch Sam?ā€ā€¦ ā€œWell Sam and Sally arenā€™t in the same room, so surely Sally canā€™t touch Samā€.

Or if say you have a view frustum, if the bounding box and view frustum donā€™t overlapā€¦ then the thing isnā€™t on screenā€¦ again, not complex intersection calculations to doā€¦ just basic bounding calculations.

10 Likes

One gotcha about Bounds to watch out for is code like this:

            Bounds _worldBox = new Bounds();

            for (var i = 0; i < renderers.Length; ++i)
            {
                _worldBox.Encapsulate(renderers[i].bounds);
            }

If you do a ā€œnew Bounds()ā€, the position (0,0,0) is part of the bounds, which you probably donā€™t want.

2 Likes

Thanks to both of you guys!

Such nice answers, it warms the heart :slight_smile:

The problem with bounds is that it doesnā€™t work well for rotated objects because then the bounds would be not the same as collider volume.

er, could you elaborate on why there is a problem, and what you want instead? Iā€™m currently debugging code that looks like what you posted, so perhaps I am hitting the issue you refer to, but I canā€™t tell whatā€™s actually wrong.

If you call encapsulate, it inflates/grows the bounds from its current position/size to encompass both itself AND the bounds passed in.

The problem is that the starting bounds are of dimensions 0 at position 0. Basically itā€™s a bounds encapsulating a single point (that point being 0,0,0).

When it inflates to say encapsulate bounds at 100,0,0 with say size 1,1,1ā€¦ youā€™ll end up with a box encapsulating bothā€¦ basically a box that is size 100.5,1,1 and positioned probably around 50.25,0,0.

See the problem?

So in BlackPeteā€™s codeā€¦ the intent of the code at first glance appears to give you a bounding box that encompasses every bounds in the renderer listā€¦ but actually it encompasses every bound in the renderer list AND a 0 sized bound at 0,0,0. If those bounds happen to overlap that 0 bound, itā€™s fineā€¦ but if those bounds arenā€™t near the origin. Yeah, itā€™s going to be a big problem.

So reallyā€¦ for BlackPeteā€™s code to properly get what the implied intent is would be to do something like:

var conjoinedbounds = renderers[0].bounds;
for(int i = 1; i < renderers.Length; i++)
{
    conjoinedbounds.Encapsulate(renderers[i].bounds);
}
2 Likes

Thanks for the explanation! That makes sense, and yeah that was the problem I was encountering (my modelā€™s origin was far off the actual mesh). In my case, I couldnā€™t assume every object had a renderer, so I needed to do descendant.TryGetComponent(out var childRenderer) and then instead of simply using the first objectā€™s renderer, while looping do the check in this first snippet: