instantiating objects at runtime, need to make sure objects don't overlap.

I am making asteroid fields for my game. Right now, the asteroids are instantiated in an ellipse. Since asteroid fields are obviously not perfectly symmetrical, I added a jitter factor into the field creator to make it so that the asteroids have some randomness to how they are placed. The problem with this is, the asteroids will usually overlap. Because they have colliders and rigid bodies, if they overlap they instantly shoot off into space. I need to figure out how to check if an asteroid will be overlapping another and make sure that it doesn’t when it’s instantiated. Here is my code thus far:

var center : Vector3;
var radiusX : float;
var radiusZ : float;
var density : float;
var spacingJitterX: float;
var spacingJitterZ: float;
var spacingJitterY: float; //orthographic camera, use sparingly
var sizeJitter : float;
var asteroids : GameObject[];

function Start () {

center = transform.position;

//get circumference of ellipse
var circum : float = 2*Mathf.PI*Mathf.Sqrt((radiusX*radiusX + radiusZ*radiusZ)/2.0);
//calculate the number of points
var numPoints : float = circum/density;
	
	for (var pointNum = 0; pointNum < numPoints; pointNum++){
		
		var i = (pointNum * 1.0)/numPoints;
		var angle = i * Mathf.PI * 2;
		var x = Mathf.Cos(angle)*radiusX + Random.Range(-spacingJitterX, spacingJitterX);
		var z = Mathf.Sin(angle)*radiusZ + Random.Range(-spacingJitterZ, spacingJitterZ);
		var y = Random.Range(-spacingJitterY, spacingJitterY);
		var pos = Vector3(x, y, z) + center;
		
		var r : int = Random.Range(0, asteroids.length);
		var asteroid : GameObject = asteroids[r];
		asteroid.transform.localScale = Vector3.one * Random.Range(1, sizeJitter);
		
		Instantiate (asteroid, pos, Random.rotation);
		
		var mesh : Mesh = asteroid.GetComponent(MeshFilter).mesh;
		
	}
}

it should be noted that the asteroids shouldn’t overlap ANYTHING. they should be able to detect other objects underneath them, such as other asteroid fields.

I appreciate any and all help. thank you

EDIT: Here is a screenshot for visual reference:

Are you placing your asteroids in 2D or 3D? It looks like 3D in your code.

You can run through each asteroid and test to see if there is an overlap between your spawned asteroid and any of the existing asteroids. I would make the collision test larger than an actual asteroid so as to provide enough space for the asteroid to spawn in and rotate, etc. you can just test two the radii of two spheres to see if they overlap, very fast test. (“First, let us assume that the chickens are spheres.” – Mathematician joke) Point in polygon tests also work if you want to get fancy.

Alternatively, divide your collision space up to in to regions and maintain a list of which asteroid is in which region. So long as your collision regions are larger than a single asteroid, and there are more collision regions than there are asteroids you can quickly scan for an empty collision region. If you are in 3D an asteroid may inhabit up to 9 collision regions, if you are in 2D an asteroid may inhabit up to 4 collision regions.

Dividing planes in a tree are another alternative, but are a lot more work to implement. Depends on how many asteroids you need to spawn and how often you need to spawn them.

awesome, i’ll try these ideas out. The asteroids pretty much just need to be spawned once ever. I can spawn as little as 15 or as many as 60 ish.

alright, so I’ve got the sphere it will be checking. Seemed like the quickest and easier of your proposed ideas. Here’s the code so far…basically just got the nesting done.

		var astArray = new Array();
		clone = Instantiate(asteroid, pos, Random.rotation);
		astArray.Push(clone);
		
		for (n=0; n<astArray.length; n++){
			var astR : float = astArray[n].GetComponent(MeshFilter).mesh.bounds.extents.magnitude;
			var p : Vector3 = astArray[n].transform.position;
			var isOverlap : boolean = Physics.CheckSphere(p, astR);
			
			if (isOverlap == true){
				print (astArray[n]);

so pretty simple. It prints whatever asteroids are colliding. I just need to figure out what to do with them now that I can see that they collide.

Awesome job! Glad you got something working for you.

How about this for a suggestion, it isn’t the most elegant or fastest, but when you detect an overlap, pick a new random position for the asteroid and perform your collision check again.

If I were doing this particular solution and I just wanted to get it working as soon as possible, I would keep a list of asteroids that have been generated, and then for each asteroid that needs to be created, pick a random position, determine if an asteroid is at that position based on a simple radius check, if no asteroid is there, generate your asteroid at that location otherwise pick a new random position and check again. That is basically what you have right now, but you are using the built-in physics checking of Unity to do the collision check for you.

Can I ask you, when you say:

Do you mean you have a 3D asteroid field with multiple levels? Or it is all top-down 2D?

it’s all top down, but obviously the y axis must be considered. The level I want to try this out on involves using two fields that are positioned like a venn diagram, overlapping with an empty section in the middle with enemies or power ups or something inside…just playing around with level concepts. obviously there are going to be other objects in the overlap area, so the asteroids can’t spawn on top of them. this is still part of the code i’m struggling with, how to check if ANYTHING is there at initial runtime.

My second question is, is there another method of creating a sphere that might be faster than using CheckSphere? the way you worded your post made it sound like there was.

finally, is it possible to check the radius before the physical model of the asteroid is instantiated?

bumpity