- Home /
How does Bounds.Encapsulate() work?
I have four bounding BoxCollider2D's used for level boundaries. I'd like to know the bounds of the entire level using these four colliders. I've tried the code below using Bounds.Encapsulate to widen the bounds for each BoxCollider2D but the debug results don't seem accurate. What is missing here?
ScreenBounds = new Bounds(Vector3.zero, Vector3.zero)
BoxCollider2D[] boxColliders = gameObject.GetComponents<BoxCollider2D>();
foreach (BoxCollider2D boxCollider in boxColliders) {
Bounds current = new Bounds( boxCollider.center, boxCollider.size );
Debug.Log( "new bounds : " + current );
ScreenBounds.Encapsulate( current );
Debug.Log( "Encapsulate results : " + ScreenBounds.extents);
}
Debug log values:
new bounds : Center: (-1.0, -13.6, 0.0), Extents: (22.5, 2.0, 0.0)
Encapsulate results : (22.5, 7.8, 0.0)
new bounds : Center: (-1.0, 13.6, 0.0), Extents: (22.5, 2.0, 0.0)
Encapsulate results : (22.5, 15.6, 0.0)
new bounds : Center: (-21.5, 0.2, 0.0), Extents: (2.0, 15.5, 0.0)
Encapsulate results : (22.5, 15.6, 0.0)
new bounds : Center: (19.3, 0.2, 0.0), Extents: (2.0, 15.5, 0.0)
Encapsulate results : (22.5, 15.6, 0.0)
Answer by Bunny83 · Jun 10, 2014 at 05:56 AM
You have two problems here:
you initialize your ScreenBounds with "new Bounds(Vector3.zero, Vector3.zero)". These "bounds" will be extended to include the given bounds. Since 0,0,0 isn't part of any bounds the result will be wrong.
you use the boxcolliders local center and local size and treat them like world space coordinates. So the result will never be right.
You have to initialize your ScreenBounds with the first collider in your array. This can be done like this:
BoxCollider2D[] boxColliders = gameObject.GetComponents<BoxCollider2D>();
ScreenBounds = new Bounds(Vector3.zero, Vector3.zero)
foreach (BoxCollider2D boxCollider in boxColliders)
{
if (ScreenBounds.extents == Vector3.zero)
ScreenBounds = boxCollider.bounds;
ScreenBounds.Encapsulate( boxCollider.bounds );
}
An alternative would be:
BoxCollider2D[] boxColliders = gameObject.GetComponents<BoxCollider2D>();
if (boxColliders.Length > 0)
{
ScreenBounds = boxColliders[0].bounds;
foreach (BoxCollider2D boxCollider in boxColliders)
{
ScreenBounds.Encapsulate( boxCollider.bounds );
}
}
else
ScreenBounds = new Bounds(Vector3.zero, Vector3.zero)
ps: You should always use the .bounds property since boxCollider.center and boxCollider.size are in local space. So center is just the offset from the gameobjects pivot. The bounds property also considers if the collider / gameobject is rotated / scaled.
awesome! thank you. i am using BoxCollider2D and there doesn't appear to be a bounds property, even though it's in the docs... not sure why that is :/
"Type UnityEngine.BoxCollider2D' does not contain a definition for
bounds'"
update: it must have been my version on mac, just updated and bounds displayed properly :)
Answer by ayyappa · Dec 29, 2014 at 07:54 PM
For those who has some more confusions, here is the code which can explain in understanding. Basically we are considering first one as initial bounds and make union with other bounds. If we include empty bounds initially it will try to enclose that point as well which is not we expect.
Bounds bounds;
void CalculateBounds()
{
Bounds tempBounds = new Bounds();
//Calculate the bounds of enclosed renderers
for(int i=0; i<m_listOfRenderers.Count; i++)
{
Renderer each = m_listOfRenderers[i];
if(i == 0)//Copying first one initially
{
tempBounds = each.bounds;
}
else
{
tempBounds.Encapsulate(each.bounds);
}
}
//Assign it to original bounds.
bounds = tempBounds;
}
void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireCube(bounds.center, bounds.size);
Gizmos.color = Color.red;
Gizmos.DrawSphere(bounds.center, 0.1f);
}
Your answer
Follow this Question
Related Questions
Encapsulate Bounds Problem [SOLVED] 1 Answer
BoxCollider2D not colliding as expected 0 Answers
How to set screen boundaries? 1 Answer
My RigidBody2D+BoxCollider2D is getting stuck on corners 1 Answer
touch position to world position 2D 2 Answers