Collider.bounds.size not changing when object is rotated

I’m trying to get the bounds size of an object using Collider.bounds.size.
My understanding is that the bounds should always fully enclose the object, so I would expect the size to change when the object is rotated.
However, when I use this code to get the bounds size, it stays the same even after rotating the object.
What am I missing?

Here is the part of the code I wrote:

    duplicated.transform.rotation = Quaternion.Euler(30, 0, 30);
    tempBounds = tempCollider.bounds;
    Vector2 size1 = tempBounds.size;
    sizes.Add(size1);

    duplicated.transform.rotation = Quaternion.Euler(0, 30, 30);
    tempBounds = tempCollider.bounds;
    Vector2 size2 = tempBounds.size;
    sizes.Add(size2);

    duplicated.transform.rotation = Quaternion.Euler(0, 30, 90);
    tempBounds = tempCollider.bounds;
    Vector2 size3 = tempBounds.size;
    sizes.Add(size3);

All size1, size2, and size3 are the same.

Because changing the Transform only changes the Transform. It doesn’t go away and touch every component on the GameObject and its children.

When physics runs (by default during the FixedUpdate) it sees that you’ve modified the Transform and is forced to update everything on that GameObject (which isn’t a good thing to do btw). Only then will the collider change including its bounds.

Is this 2D physics? If so, you need to change the Rigidbody2D pose directly. Still, this isn’t how physics wants to run. I believe doing the same on 3D physics will be the same.

@MelvMay Thank you very much for your prompt reply!

After testing the bounds sizes by rotating to different angles during a fixed update, I observed that the sizes do change. I’m wondering if this means it can’t be achieved in a single frame.

The thing I’m trying to do is to check if the 3D object will go out of the screen and resize it in advance since the user will be rotating it 360 degrees, and our app is responsive to a wide range of screen sizes.

You can use Physics.SyncTransforms() to force the collider bounds to update after modifying the Transform.

It works! You saved my day! Thanks a lot!

Be careful though, this isn’t a good pattern and was implemented for backwards compatibility from years ago. This checks all transforms and updates all bodies. It’ll cause performance hell at scale. The reality is that you should always avoid changing Transforms when physics is involved and always try to use the Rigidbody(2D) API to effect changes.

1 Like

In Unity 2022LTS I do not see this behaviour. Yes, rotation is honored. But no, the transform is not (in particular: the transform’s scale appears to be ignored?)

e.g. with Physics (3D):

  1. Collider.bounds returns a dimensionless bounds that’s in the object’s LOCAL scale
  2. … but WORLD position

I say “dimensionless” because: Bounds has no field for “scale” so …if you don’t have a reference to the Collider/Transform that generated that Bounds object, you have no idea what the “size” or “extents” is.

I had assumed Bounds would return WORLD scale in all cases (to go with the fact it returns WORLD position - even though in Editor it’s displayed as, and edited as, LOCAL position and scale)

The docs are useless, they have just one sentence, which appears to be false: “The world space bounding volume of the collider” - https://docs.unity3d.com/ScriptReference/Collider-bounds.html - but in testing that appears to be untrue. e.g. SphereCollider of size 0.01 (Inspector shows “radius: 0.01”), but with a parent of scale 100,100,100, consistently returns a Bounds of size 0.01 (which is definitely not true in world space!).

… the Unity Editor however renders that in world-space correctly as a green collider-sphere of radius 1,1,1

Tha Transform scale is not ignored. That would mean nobody could scale any 3D physics collider.

btw, if you’re seeing a discrepancy in 3D physics for things such as “Bounds” then you should report a bug. I am not a 3D physics dev but 2D physics. If you see a problem in 2D physics then I can investigate it for you.

To confirm though, Bounds is supposed to be the AABB in world-space that encapsules the Collider in question.

My point above though was that Transform scaling itself is working.

1 Like

Maybe there’s an issue when you do this on a parent with respect to the “Bounds” property calculation, maybe it’s always been like that for 3D or it’s a regression. Not sure.

FYI - converting this to a 1-line reproduction in a virgin project, using only Unity built-in meshes … it works as expected and as you described.

So apparently it’s something odd about the meshes in my main project. I’ll dig further, thanks.

1 Like

There have been instances where changing something in the inspector is not signalling a change whereas directly using the API does (even the opposite) so be wary of that; it might aid you narrowing it down.

Good luck.

ARGH. My mistake:

Mesh.bounds is incompatible with Collider.bounds

…and deep in my code I was checking “if( there’s a mesh of certain kind ) return mesh.bounds instead of collider.bounds”

From the docs:

Collider.bounds: “The world space bounding volume of the collider”
Mesh.bounds: “bounding box of the mesh in its own space, so the bounds don’t change if you change the Transform position, rotation or scale”

TL;DR: Bounds is used interchangeably in Unity to be in local-or-world space, with no way to know which space a given struct is from.

No way to know apart from the docs stating it or do you mean that the Bounds struct should have some kind of flag indicating whether it contains local or world space values? Adding a flag for that would be wasteful and, if I’m honest, a bit pointless as most devs who read that value know it’s source and use it appropriately.

Academically: It’s too late for Unity by 20 years on this :slight_smile: (c# had no support for it back then, if I remember correctly - but Unity’s C++ parts would have been fine, and off the top of my head they would have just mapped bytes directly into a pair of C# classes), but the ideal would have been for Bounds (and Vector) to maintain space via type-safety. typedef’ing would have meant the memory layouts were identical, but compiler would detect all cases of the (almost always incorrect) attempt to move between local and world space without using an explicit transformation of some kind.

“this world space value was used as a local space value” is one of the most common nasty bugs I see in 3rd party Unity projects - there’s no reason for it, it should not be possible (in modern software engineering: it isn’t - we all learned our lessons from OpenGL’s typeless C interfaces and the pain there :)), but it’s so easy for a single engineer to accidentally do this and unless everyone else is watching very closely they don’t spot it.

(and there have been plenty of cases of Unity staff making this mistake, it’s very easy to do, and shipping broken APIs because of it - back in the early days of Unity we had to log a lot of bugs on things like “you forgot to take account of non-uniform scale when you wrote this class” - many devs only test for scale = 1,1,1 … I think there are even some Unity APIs where they gave up and just updated the docs to say ‘requires 1.1.1 scale objects’, not because it can’t, but because the API had been live with bad behaviour for too long to fix it)

I see, the dev doesn’t know what Vector3/Bounds/Float contains and some magic type-safety would solve that and it’s all the fault of Unity. :wink:

I also see things like “this float value is used as local-space offset and not world-space offset” but no amount of “type safety” would solve it. I agree though that there are certainly things that could do with type-safety, I’m looking at you “LayerMask” and your damn implicit “int” operator which causes so much pain!

In this case though, it sounds like devs not understanding the data due to not reading the docs. If the docs are vague/ambiguous then that should be fixed.

I guess we all have opinions on stuff like this so this is just us with a slightly different opinion.

TBH, all these posts are way off-topic for this thread thought which was about the dev not understanding that changing a Transform does nothing to the physics system until a simulation has run.