Center of a GameObject with Bounds?
I'm trying to find the center of a GameObject using the renderer bounds. Some of my GameObjects have a renderer on the parent where the script is attached, while others are grouped under an empty GameObject, so I need a method that accounts for both.
I am using the following code to try and add all the renderers of the children to a single object, then get the center point of the combined bounding box.
protected Bounds _combinedBounds;
protected Renderer _renderer;
void Awake(){
_renderer = GetComponent<Renderer>();
if (_renderer){
_combinedBounds = _renderer.bounds;
}
else{
_combinedBounds = new Bounds();
}
Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>();
if (renderers.Length > 0){
for (int i = 0, len = renderers.Length; i < len; i++){
_combinedBounds.Encapsulate(renderers[i].bounds);
}
}
Debug.DrawLine(_combinedBounds.center, new Vector3(0,50,0));
}
Below you can see that I've added the script to two separate GameObjects. You can also see that the results are way off center. Further, if I try to move the objects from those points, the bounds get even more off-center.
It seems like the farther I go from the center, the more off everything becomes. Does anyone know what I can do to get the center point of an object painlessly?
why is transform.position insufficient? IS it because you need to center of multiple objects? If so, would the AVERAGE transform.position work?
Transform.position doesn't always get the center of an object, especially groups of them.
See the image below.
Aditionally, I'd still need to deal with the bounds in order to get things like the corners of the bounding box.
"Transform.position doesn't always get the center of an object"
This actually depend on how you define you model. If you create the mesh such that it's center is at model/local-coordinate (0,0,0), then transform.position, WILL always be the center of THAT mesh.
"groups of them": It's easy to compute the average position of a group of objects: If they are all the same size, this would in fact yield the center position of the set. If they are not all the same size, they wouldn't cut it.
"Bounding box" Well, THAT certainly eli$$anonymous$$ates using transform.position alone! $$anonymous$$y suggestion is now $$anonymous$$oot :)
I guess it's not quite clear what "center" you mean. It looks to me, like you are computing the total bounds (and center) correctly (you can debug.drawline the bounds [xyz-$$anonymous$$-max] to confirm: the diagonals should intersect at the center). Perhaps the bounds-center is not what you want? Perhaps you want the center-of-mass, or center-of-volume?
This is what I'm looking for. The GameObject on the left has one child inside it, and the one on the right has 4. I want to get the collective center of the entire group, as well as the bounds that confine them so that I can also check for the corners.
Here's another example:
Given a group of objects, I'd like to return their collective bounds. $$anonymous$$y understanding was that that was what Encapsulate allowed you to do, but it always returns a position completely off the rails from the actual object.
sorry dude, you obviously put effort into those pics, but I'm still unclear. If you can draw the current-result FINAL bounds value you get (after encapsulating child bounds), it might clear things up for me.
You second image is exactly what I would expect the results of your code to be; I must be misunderstanding the symptom.
Answer by Glurth · May 07, 2016 at 02:18 PM
AH HA! That last pic and notes had the key piece of information need to spot the bug: The fact that (0,0,0) was always included in the bounds.
The REASON this happens is: according to you code, if the root object does not have a renderer, you start the bounds off with:
_combinedBounds = new Bounds();
This will create a new bounds object, with min, max, center of (0,0,0). When you call Encapsulate- you are extending the bounds to include the new boundaries, but this does NOT REMOVE the original bounds you started with, they are joined together. So, you newly encapsulated bounds will ALSO include (0,0,0).
To eliminate this error, do NOT initialize the bounds with new Bounds()
, instead wait until you have an actual render object with bounds, and THEN start combining.
That was it.
protected Bounds _combinedBounds;
protected Renderer _renderer;
void Awake(){
Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>();
if (renderers.Length > 0){
_combinedBounds = (renderers[0].bounds);
for (int i = 1, len = renderers.Length; i < len; i++){
_combinedBounds.Encapsulate(renderers[i].bounds);
}
}
Debug.DrawLine(_combinedBounds.center, new Vector3(0,50,0));
}
looks good but watch-out: with this code it's possible for _combinedBounds to end up NULL (if no renders are found on startup), in which case this would generate a nullReferenceException : _combinedBound.center
I tried using this, but when I used it on an animated object, the bounds never changed. How can I get the bounds on an object that is animated and have it update?
There are a few different bounds functions, some return world-coordinates, some return local-coordinates. $$anonymous$$ake sure you are not using the mesh bounds, for example, which returns local-coordinates.
Your answer
Follow this Question
Related Questions
How Can I assign a gameobject via script? 0 Answers
What to use instead of GameObject.Find and GetComponent 2 Answers
Get component from parent of children hittet with raycast 1 Answer
C# GameObject disabled scripts of its children after SetActive(false) 1 Answer
Custom inspector and GameObject Children 0 Answers