- Home /
physics.overlapshere not working as expected with objects being placed at random
Hi there,
I'm tearing my hair out over this and I feel like its something super simple that I'm just not seeing.
I have a 5 spheres (ArchiveNodes in this example) that I'm hoping to spawn on the edge of a circle, radius 3, at the origin. I'm using physics.overlap sphere to check whether to prospective position to place my sphere, tagged archive, is going to overlap with any other archives?
At the beginning there are no spheres anywhere near this circle they are pooled somewhere else off in the scene. When they spawn in they sometimes overlap which is exactly what I don't want to happen.
What's strange is that if I place existing objects with colliders on the circle edge such as cubes that are also tagged Archive they never overlap with them? (All the spheres being spawned also have sphere colliders on)
I've tried taking this spawn out of the Awake function into OnKeyDown.
Here is my code which I based off this answer from a couple years ago:
private void Awake()
{
ThisTransfom = GetComponent<Transform>();
for (int i = 0; i < ArchivePrefab.Length; i++)
{
//prospective position for spawn
Vector3 dir = Vector3.zero;
//whether or not we can spawn in this position
bool validPosition = false;
while (!validPosition)
{
//pick new position for potential spawn
Vector2 temp = (Random.insideUnitCircle).normalized * SphereRadius;
dir = temp;
//position is true until proven false
validPosition = true;
//collect all colliders within our obstacle check radius
Collider[] colliders = Physics.OverlapSphere(dir, .75f);
//go through each collider collected
foreach(Collider col in colliders)
{
//if collider has a matching tagged "Archive"
if(col.tag == "Archive")
{
Debug.Log(ArchivePrefab[i].name + " is touching " + col.gameObject.name + " at " + dir);
//then this is no longer a valid spawn position
validPosition = false;
}
}
}
//if we exited while loop with a valid position
if (validPosition)
{
Debug.Log("Place " + ArchivePrefab[i].name + " at " + dir);
GameObject point = ArchivePrefab[i];
Node node = point.GetComponent<Node>();
point.SetActive(true);
point.transform.position = dir;
point.transform.parent = ParentCircle;
Vector3 rot = (Vector3.zero - point.transform.position).normalized;
node.AlignObj.rotation = Quaternion.LookRotation(rot, Vector3.right);
}
}
}
I had pretty much the same code before but with a do while instead however being a verified answer and being seemingly exactly what I needed I thought I would go with this instead!
Thanks in advance for taking the time to help! Really appreciate it!
Answer by Don_Raphael · Apr 30, 2020 at 12:58 PM
I have managed to fix it thanks to this answer ! Have placed the the spawn code in a coroutine in awake which contains a WaitForFixedUpdate() when it resolves to allow time to check the colliisions. It's not ideal as they load in a bit of a staggered way due to the frames but I'll do some sort of animation or something to cover that.
Here is the updated code:
private void Awake()
{
ThisTransfom = GetComponent<Transform>();
StartCoroutine(SpawnArchives());
}
public IEnumerator SpawnArchives()
{
for(int i = 0; i< ArchivePrefab.Length; i++)
{
//prospective position for spawn
Vector3 dir = Vector3.zero;
//whether or not we can spawn in this position
bool validPosition = false;
while (!validPosition)
{
//pick new position for potential spawn
Vector2 temp = (Random.insideUnitCircle).normalized * SphereRadius;
dir = temp;
//position is true until proven false
validPosition = true;
//collect all colliders within our obstacle check radius
Collider[] colliders = Physics.OverlapSphere(dir, .75f);
//go through each collider collected
foreach (Collider col in colliders)
{
//if collider has a matching tagged "Archive"
if (col.tag == "Archive")
{
Debug.Log(ArchivePrefab[i].name + " is touching " + col.gameObject.name + " at " + dir);
//then this is no longer a valid spawn position
validPosition = false;
}
}
}
//if we exited while loop with a valid position
if (validPosition)
{
Debug.Log("Place " + ArchivePrefab[i].name + " at " + dir);
GameObject point = ArchivePrefab[i];
Node node = point.GetComponent<Node>();
point.SetActive(true);
point.transform.position = dir;
point.transform.parent = ParentCircle;
Vector3 rot = (Vector3.zero - point.transform.position).normalized;
node.AlignObj.rotation = Quaternion.LookRotation(rot, Vector3.right);
yield return new WaitForFixedUpdate();
}
}
}
Feel like a muppet for asking (I did spend a long long long time trying to get this yesterday before asking on here). Hopefully the updated code can help someone else in the same positions.
Any improvements on this method or more elegant solutions still welcome!
Answer by mfvlk · Apr 30, 2020 at 01:28 PM
Thanks for recognizing my answer! I'm also still interested in more elegant solutions, so if there are any updates I'd love to hear
Your answer
![](https://koobas.hobune.stream/wayback/20220612232904im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
[Solved] Detecting objects with OverlapSphere within the frame they are created? 1 Answer
Preventing Spawn Overlap With Spheres 1 Answer
Detect collider collision ,identify and access colliding colliders 0 Answers
Why does this not work (Involves instantiating objects in response to a collision*) 1 Answer
how to access parent script from child object with overlapsphere in a multiplayer game 0 Answers