Collider.bounds position is wrong?

I’ve done a lot of looking through forums but noone seems to have the same issue.

I instantiate a prefab (SlidingBarrier) as a GameObject which has a box collider. I randomly position the object. Then I check if the bounds of the object intersects with the bounds of another GameObject that I had earlier instantiated from a different prefab (GoalStalker). This check always returns true. At this point I print the position of the bounds.

I have setup another check for these bounds in the OnDrawGizmo() method. The bounds are drawn with a wire cube in magenta if they aren’t intersecting, and yellow if they are. I then print the position and size of the bounds.

The second set of positions (from OnDrawGizmo) are different to the first, but only on the x and z axes, (I assume only these axes because I force the y to remain the same as prefab).

My question is: why does the position of the bounds in the first check not get updated, but they are in the second check? And how can I make it so the bounds do get updated before the first check?

Here’s my code:

    public void Start()
    {
        hazards = new List<GameObject>();
        GameObject gameControllerObject = GameObject.FindWithTag("GameController");
        if (gameControllerObject != null)
        {
            gameController = gameControllerObject.GetComponent<GameController>();
        }
        SetHolePosition();
        BuildFloors();
        AddHazards();
    }

private void AddHazards()
    {
        RemoveWalls();
        AddGoalStalker();
        AddSlidingBarrier();
    }

    private void AddGoalStalker()
    {
        Vector3 pos = new Vector3(hole.transform.position.x, goalStalkerPrefab.transform.position.y, hole.transform.position.z);
        InstantiateObject(goalStalkerPrefab, hazardType.GoalStalker, pos);
    }

    private void AddSlidingBarrier()
    {
        Vector3 pos = RandomPos(hazardType.SlidingBarrier);
        pos.y = hazardType.SlidingBarrier.minPos.y;
        InstantiateObject(slidingBarrierPrefab, hazardType.SlidingBarrier, pos);
    }

    private void InstantiateObject(GameObject prefab, Hazard hazard, Vector3 pos)
    {
        string hazardName = hazard == hazardType.GoalStalker ? "GoalStalker" : "SlidingBarrier";
        int round = gameController.RoundsCreated() + 1;
        int randInt = Random.Range(0, round);
        if (round >= hazard.firstRound && randInt >= hazard.chance)
        {
            GameObject obj = Instantiate(prefab, hazardDirectory, false) as GameObject;
            float rot = RandomRot(hazard);
            obj.transform.position = hazardDirectory.position + pos;
            obj.transform.Rotate(Vector3.up, rot, Space.Self);

            bool checkIntersect = CheckIntersect(obj);
            hazards.Add(obj);
        }
    }

    private bool CheckIntersect(GameObject obj)
    {
        Bounds bounds = obj.GetComponent<Collider>().bounds;
        foreach (GameObject other in hazards)
        {
            bool intersects = bounds.Intersects(other.GetComponent<Collider>().bounds);
            Debug.Log("checkIntersect = " + intersects + "; at center " + bounds.center.ToString() + "; with size " + bounds.size.ToString() + ";");

            if (intersects)
            {
                return true;
            }
        }
        return false;
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.magenta;
        foreach (GameObject hazard in hazards)
        {
            Bounds bounds = hazard.GetComponent<Collider>().bounds;
            foreach (GameObject other in hazards)
            {
                if (hazard != other)
                {
                    if (bounds.Intersects(other.GetComponent<Collider>().bounds))
                    {
                        Gizmos.color = Color.yellow;
                    }
                }
            }
            if (hazard.name == "SlidingBarrier(Clone)")
            {
                Debug.Log("OnDrawGizmos() - bounds at center " + bounds.center.ToString() + "; with size " + bounds.size.ToString() + ";");
            }
            Gizmos.DrawWireCube(bounds.center, bounds.size);
        }
    }

It turns out that the physics were not being updated to match the new transform of the hazard. This is resolved using Physics.SyncTransforms() just after updating the transform of the GameObject in InstantiateObject()

I found the answer on this forum

    private void InstantiateObject(GameObject prefab, Hazard hazard, Vector3 pos)
    {
        string hazardName = hazard == hazardType.GoalStalker ? "GoalStalker" : "SlidingBarrier";
        int round = gameController.RoundsCreated() + 1;
        int randInt = Random.Range(0, round);
        if (round >= hazard.firstRound && randInt >= hazard.chance)
        {
            GameObject obj = Instantiate(prefab, hazardDirectory, false) as GameObject;
            float rot = RandomRot(hazard);
            obj.transform.position = hazardDirectory.position + pos;
            obj.transform.Rotate(Vector3.up, rot, Space.Self);

            Physics.SyncTransforms(); // <<< Here is the fix

            bool checkIntersect = CheckIntersect(obj);
            hazards.Add(obj);
        }
    }

Well it’s hard to tell from your given information However I would suggest to move the line:

Gizmos.color = Color.magenta;

into the first foreach loop right at the start. Otherwise as soon as you have one overlapping collider you set the color to yellow and it would draw all following collider bounds yellow, regardless if they are colliding or not. You may want to print out the names of the objects that actually intersect. Maybe you’re looking at the wrong objects? The numbers in your logs are kinda useless for us since we can’t check where each object is located.

Also keep in mind that you cal pass a context object to your Debug.Log calls as second parameter. That way you can click on the message in the console and Unity will highlight that context object. It may help to figure out which objects are actually colliding with which.

Thanks for your feedback, I’ve made the changes you’ve suggested (see below) but I still can’t work out why the check in CheckIntersect() returns true when the check in OnDrawGizmos() returns false.

The gizmos now draw as white if there is just one hazard, magenta if there are multiple hazards without intersection, and yellow if there are multiple hazards and at least one is intersecting (only the ones ibntersecting will be yellow. In this case there are only ever a max of 2 hazards per board, so everything will be yellow if there’s an intersection).

I didn’t know you could pass a context obj to the log so thanks for that nifty piece of info :slight_smile: In the below image I have selected the logs that correspond with the top board, and the SlidingBarrier that corresponds to the logs so the actual position of the hazard can be seen.

As you can see, the CheckIntersect() thinks the SlidingBarrier is at pos (0.0, -3.8, 0.0), while the OnDrawGizmos() pos says (0.5, -3.8, -0.5) I figure these are rounded up from the actual pos values which are (0.4874206, 1.25, -0.5118654). The y position is different due to the logs being in world space and the actuasl being in local space, the first Board object is at position (0, -5, 0)

Code Changes:

private void OnDrawGizmos()
    {
        foreach (GameObject hazard in hazards)
        {
            Bounds bounds = hazard.GetComponent<Collider>().bounds;
            foreach (GameObject other in hazards)
            {
                if (hazard != other)
                {
                    if (bounds.Intersects(other.GetComponent<Collider>().bounds))
                    {
                        Gizmos.color = Color.yellow;
                        Debug.Log("OnDrawGizmos() - " + hazard.name + " intersects with " + other.name + " where " + hazard.name + " bounds are:

"
+ "Center = " + bounds.center.ToString() + "; Size = " + bounds.size.ToString(), hazard);
}
else
{
Gizmos.color = Color.magenta;
Debug.Log("OnDrawGizmos() - " + hazard.name + " does not intersect with " + other.name + " where " + hazard.name + " bounds are:
"
+ "Center = " + bounds.center.ToString() + "; Size = " + bounds.size.ToString(), hazard);
}
}
}
Gizmos.DrawWireCube(bounds.center, bounds.size);
}
}

private bool CheckIntersect(GameObject hazard)
    {
        Bounds bounds = hazard.GetComponent<Collider>().bounds;
        foreach (GameObject other in hazards)
        {
            bool intersects = bounds.Intersects(other.GetComponent<Collider>().bounds);
            if (intersects)
            {
                Debug.Log("CheckIntersect() - " + hazard.name + " intersects with " + other.name + " where " + hazard.name + " bounds are:

"
+ "Center = " + bounds.center.ToString() + "; Size = " + bounds.size.ToString(), hazard);
return true;
}
else
{
Debug.Log("CheckIntersect() - " + hazard.name + " does not intersect with " + other.name + " where " + hazard.name + " bounds are:
"
+ "Center = " + bounds.center.ToString() + "; Size = " + bounds.size.ToString(), hazard);
}
}
return false;
}