1
\$\begingroup\$

To be completely transparent, I more-or-less copied this question from the Unity forums since I did not get a reply.

I'm creating this system where I'm placing level chunks together and I need to collect a list of colliders that have intersected with a particular level chunk. All of this is being done within one frame (A loop is controlling this placement). A chunk is composed of several colliders.

The way I am doing this is with an OverlapBox, copying the dimensions of a collider of a particular child GameObject (named area). This is done through the following function, being called from a control script. It's meant to check for collisions that are happening within it, and return true when it's intersecting something it shouldn't.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CollisionCheck : MonoBehaviour
{
    public LayerMask m_LayerMask; //This is set to Everything in the editor

    public Collider[] collidersTouched;


    public bool IsInappropriateTouchingHappening (GameObject allowedChunk)
    {
        BoxCollider area = transform.Find("area").gameObject.GetComponent<BoxCollider>();
        collidersTouched = Physics.OverlapBox(area.bounds.center, area.bounds.size/2, Quaternion.identity, m_LayerMask);

        Debug.Log("OverlapBox picked up this many colliders: " + collidersTouched.Length);

        foreach (Collider col in collidersTouched)
        {
            Debug.Log("the collider in the obtained array: " + col.gameObject.name + col.gameObject.transform.position);
            if (!GameObject.ReferenceEquals( allowedChunk, col.gameObject) && !GameObject.ReferenceEquals( gameObject, col.gameObject))
            {
                return true;
            }
        }
        return false;
    }

    void OnDrawGizmos ()
    {
        BoxCollider area = transform.Find("area").gameObject.GetComponent<BoxCollider>();
        Gizmos.matrix = Matrix4x4.TRS(area.bounds.center, Quaternion.identity, area.bounds.size);
        Gizmos.color = Color.red;
        Gizmos.DrawCube(Vector3.zero, Vector3.one);
    }
}

It tells me that it's picked up pretty much every collider in the scene! However, when I perform an isolated test using one of the chunks that the system is using, everything checks out. Here's the code for the script I'm using for said test. It's a modified version of what's in Unity's documentation forOverlapBox.

using UnityEngine;

public class OverlapBoxExample : MonoBehaviour
{
    bool m_Started;
    public LayerMask m_LayerMask;

    void Start()
    {
        m_Started = true;
    }

    void FixedUpdate()
    {
        MyCollisions();
    }

    void MyCollisions()
    {
        BoxCollider area = transform.Find("area").gameObject.GetComponent<BoxCollider>();
        Collider[] hitColliders = Physics.OverlapBox(area.bounds.center, area.bounds.size/2, Quaternion.identity, m_LayerMask);
        Debug.Log("Number of colliders hit in test: " + hitColliders.Length);
    }

    //Draw the Box Overlap as a gizmo to show where it currently is testing. Click the Gizmos button to see this
    void OnDrawGizmos()
    {
        BoxCollider area = transform.Find("area").gameObject.GetComponent<BoxCollider>();

        Gizmos.matrix = Matrix4x4.TRS(area.bounds.center, Quaternion.identity, area.bounds.size);
        Gizmos.color = Color.yellow;
        Gizmos.DrawCube(Vector3.zero, Vector3.one);
    }
}

The gizmo in this second script is showing me the volume of the OverlapBox correctly, but in the first script, it's not.

Does anyone have any ideas? I cannot imagine what makes the two boxes different, aside from the OverlapBoxExample script performing its OverlapBox() inside FixedUpdate instead of frame 1 like it does in my implementation. I don't know why that would affect the size, however.

To recap, the whole issue is that the I'm attempting to create in the first script is inexplicably large. Also, Both the test and the implementations' gizmos show the volume/position of the OverlapBox I want. Please let me know if more information is needed.

\$\endgroup\$
  • \$\begingroup\$ You say the first script fires in frame 1? Have you allowed the physics engine to update its model of where everything is using SyncTransforms before doing your first query? \$\endgroup\$ – DMGregory Aug 13 '19 at 4:04
  • \$\begingroup\$ So I looked it up in the docs and tested it out. You're right, it works! The test must have only worked because it was able to work with those updated transforms. I feel silly for not realizing this had to be done. Thanks! \$\endgroup\$ – LordValkyrie Aug 13 '19 at 13:53
  • 1
    \$\begingroup\$ If you've solved your problem, please consider sharing your solution as an Answer to help others. :) \$\endgroup\$ – DMGregory Aug 13 '19 at 14:16
2
\$\begingroup\$

Thanks to what DMGregory pointed out, I was able to solve my issue. I had to use Physics.SyncTransforms (Unity Docs) before the first time I called OverlapBox().

It turns out that the OverlapBox wasn't incredibly large, but that the transforms needed to be updated manually since everything was happening in one frame. As a result, the OverlapBox was the right size, but all of the colliders that I had moved that frame hadn't actually been moved yet according to the physics engine. So, I just needed to make this call before using OverlapBox:

Physics.SyncTransforms()
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.