- Home /
Sphere Collision Overlap Detection
I have been scratching my head with this problem for the last few hours. I'm randomly generating multiple objects (animals) which all have sphere colliders on various points on a small map. I'm trying to accurately detect when the animals are spawned on top of each other, so that I can retry to place them so they are not touching. The problem is that even when they are nowhere near each other, they all claim to be touching the first animal that is generated. Every time I spawn an animal, I call the checkCollision function and pass along the newly spawned creature.
//Check if colliders touching
bool checkCollision(GameObject obj)
{
SphereCollider objCollider = obj.GetComponent<SphereCollider>();
Collider[] touching = Physics.OverlapSphere(objCollider.bounds.center, objCollider.radius);
//print(touching.Length);
foreach(Collider touch in touching)
{
//avoid detecting itself or the tile it's placed on![alt text][1]
if(touch.gameObject != obj && !touch.gameObject.CompareTag("Tile"))
{
print(obj.name + " touching " + touch.gameObject.name);
return (false);
}
}
return (true);
}
You can see from the attached picture, that they are nowhere near each other when detecting the collision. In a different script, I used the DrawGizmos function to draw a sphere based on the collider bounds center and radius, just as I'm doing to check for the collision. The Gizmos sphere is what I'd expect it to be.. But I do not understand how they are detecting collision between each other. Even more puzzling, animals that actually are colliding do not print that they've detected the collision. If it matters, the sphere colliders on each of the animals are marked with "isTrigger" false and on the rigidbody "isKinematic" false.
Here is the code that spawns them. The animals are positioned, and then checked for collision.
GameObject animalClone = Instantiate(animalPrefab, animalHolder.transform);
animalClone.name = Random.Range(1, 3000000).ToString();
float x_rand = Random.Range(-xDim, xDim);
float z_rand = Random.Range(-zDim, zDim);
animalClone.transform.position = gameObject.GetComponent<Renderer>().bounds.center + new Vector3(x_rand, 0, z_rand);
placedAnimal = checkCollision(animalClone);
[1]: /storage/temp/152505-capture.png
I've found part of the issue.. When printing the objCollider.bounds.center value, all objects have the same center bounds. This explains why they register as touching the first one, but I do not understand why they all show the same given that each animal is positioned prior to checking for collision.
Okay, I tried rewriting the code to check for intersecting bounds between game objects. What this has shown me is that the sphere colliders are not updating their positions when the check happens. Can someone answer, shouldn't the colliders have updated positions after their objects are moved?
Answer by Marshal_Alessi · Feb 09, 2020 at 01:11 AM
Alright, I've determined that this is indeed a unity bug that it cannot register the updated sphere bounds in time to check if collision has occurred. I've fixed the issue by instead checking between the distance of all spawned objects as I've spawned them, which has given me the desirable result.
No, it's not a bug. You just missed how the physics system works ^^.
Answer by Bunny83 · Feb 09, 2020 at 01:19 AM
You may want to have a look at my answer over here which I wrote just about 12 hours ago. The position and orientation of colliders are usually only updated at the next physics step. The actual collider representation in the physics system is not a Unity object. For 3d physics Unity uses Nvidia's PhysX and for 2d physics Box2d is used. You have to use Physics.SyncTransforms after you did any changes to a collider in order to see the result immediately.
Apart from that I would highly recommend to use a layer mask and put your relevant objects on the same layer. That way you don't need to check for your "Tile" tag. It also helps with performance.