Before I ask the question I will explain what I’m trying to do. I currently am trying to load in an object of a massive size into a tiny room so I want to scale the object down to fit inside a boxcollider that has been scaled to fit in the room.
The gameobject holds multiple child objects, example being a chair has four leg child objects. So what I’ve been trying to do is getting the transform of each individual child object and then set their scale until they fit inside the boxcollider.
Some pictures to illustrate what I’m attempting to do.
Rigidbody d=b.AddComponent<Rigidbody>();
d.isKinematic = true;
d.useGravity = false;
BoxCollider s=b.AddComponent<BoxCollider>();
s.isTrigger = true;
Transform[] c = b.GetComponentsInChildren<Transform>();
Renderer[] a = b.GetComponentsInChildren<Renderer>();
//Get the different boxcollider sizes
float targetsize = s.bounds.size.z;
float targetsize1 = s.bounds.size.x;
float targetsize2 = s.bounds.size.y;
//Loop through all the Transforms in an object
for (int i = 0; i < c.Length; i++)
{
//Assign Renderer bounding sizes to floats (For my own understanding)
float currentsize = a[i].bounds.size.z;
float currentsize1 = a[i].bounds.size.x;
float currentsize2 = a[i].bounds.size.y;
//Get scale of transforms in object
Vector3 scale = c[i].localScale;
//Reduce or increase size to match the boxcollider size
scale.z = targetsize * scale.z / currentsize;
scale.x = targetsize1 * scale.x / currentsize1;
scale.y = targetsize2 * scale.y / currentsize2;
//Assign transform scale to the new scale
c[i].localScale = new Vector3(scale.x, scale.y, scale.z);
You could try an approach where you calculate the center and bounds of the big object and the you position the center of the big object into the center of the bounding box then calculate the absolute diffirence between the two bounding boxes and scale the big object down with that factor.
In your code you loop through alot of objects but you don’t have to you can just place everything within one transform/gameobject and scale that one down…
First and foremost, remember that the bounds of an object is an axis aligned box. If you rotate it, its bounds change in size. So make sure when you’re comparing bounds, you have everything rotated along similar axes.
Next, you don’t have to scale each individual child object. If you scale a parent Transform, all the children get scaled with it.
You can easily calculate the bounds of all colliders (even if they don’t have a Rigidbody) by getting all the colliders of the children:
var colliders = someParent.GetComponentsInChildren<Collider>();
Then you can loop over all those and join the bounds to get the entire bounds of the entire parent.
Rect bounds = colliders[0].bounds;
foreach(var c in colliders) bounds = bounds.Encapsulate(c.bounds);
Then you can compare the size of the this bounds and the bounds of the box it’s gotta fit in, and scale ‘someParent’ by that.
var szA = otherBounds.size;
var szB = bounds.size;
var scale = new Vector3(szA.x / szB.x, szA.y / szB.y, szA.z / szB.z);
someParent.localScale = scale;
4 Likes
Sorry, can you explain what bounds.Encapsulate does? I went to the documentation but I still don’t quite get it.
On another note, the children do not have any colliders, they only have a Mesh renderer and filter. The parent gameobject has the rigidbody and collider.
It returns a bounds that fits both bounds in it.
If you say:
bounds.Encapsulate(otherBounds);
You get a bounds that is the size of bounds + otherBounds.
The red would be the result.
As you can see, the bounds grow to ‘encapsulate’ the 2 bounds that generate it.
(sorry, in previous post I said “bounds = bounds.Encapsulate(…)”, but the function returns void, and actually modifies the state of the calling bounds… my bad)
3 Likes