Random generation problem.

Hello.

Latelly I’ve been working on random star system generator, but I have one problem.

Sometimes, planets spawn on same orbits which obviously shouldn’t happen, but I don’t know how to solve this problem.

Here’s an example:

[11583-generation+problem.jpg|11583]

As you can see, 3 planets share the same orbit.

Here’s the generation code:

Vector2 pos = new Vector2(Random.Range(-260,260) ,Random.Range(-260,260));		
Instantiate(prefab, new Vector3(pos.x,0,pos.y), Quaternion.Euler(0,0,0));

I hope that someone can help.

-Xentarok

P.S.: English isn’t my native language, so I apologize for any mistakes.

Ok, cool, thanks for the clarification. If it is only happening occasionally, this is a standard behavior of a random number generator, you will occasionally get the same result. If you want to eliminate dupes, what you can do is register each position after you create it, then surround the random generation line with a do while loop that checks the result against your registered list. If it already exists continue, otherwise break out.

something like this:

List<Vector2> positions = new List<Vector2>();
while (planetcount < MaxPlanets)
{
    Vector2 pos;
    do
    {
        pos = new Vector2(Random.Range(-260, 260), Random.Range(-260, 260));
    } while (positions.Contains(pos));
     positions.Add(pos);
     Instantiate(prefab, new Vector3(pos.x, 0, pos.y), Quaternion.Euler(0, 0, 0));
    planetcount++;
}

Alternatively you could just compare one value (x or y) to prevent the same orbit and not just identical placement

To check just the Orbit (lets assume your Y is the distance)

List<int> positions = new List<int>();
while (planetcount < MaxPlanets)
{
    Vector2 pos;
    do
    {
        pos = new Vector2(Random.Range(-260, 260), Random.Range(-260, 260));
    } while (positions.Contains(pos.y));
    positions.Add(pos.y);
    Instantiate(prefab, new Vector3(pos.x, 0, pos.y), Quaternion.Euler(0, 0, 0));
    planetcount++;
}

To check for dupes within a given allowance, try the following:

List<int> positions = new List<int>();
int minDistance = 3;
while (planetcount < MaxPlanets)
{
    Vector2 pos;
    bool is_dupe= true;
    while(is_dupe)
    {
        pos = new Vector2(Random.Range(-260, 260), Random.Range(-260, 260));
        is_dupe = false
        foreach(int orbit in positions)
        {
            if(Mathf.Abs(orbit - pos.y) < minDistance)
            {
                is_dupe = true;
            }
        }
    }
    positions.Add(pos.y);
    Instantiate(prefab, new Vector3(pos.x, 0, pos.y), Quaternion.Euler(0, 0, 0));
    planetcount++;
}
  • Start a new scene
  • Attach the script below to an empty game object
  • Place a sphere at the origin (or anywhere) to represent the sun
  • Drag and drop the sun onto the ‘Sun’ variable in the empty game object
  • Move the camera back to -40 on the ‘Z’ axis
  • Hit run

After you run it once to see how the planets are placed. Uncomment the line:

//v3 = Quaternion.AngleAxis(Random.Range(0.0, 360.0), Vector3.forward) * v3;

…and then run it again to see the planets spread out.

#pragma strict

var sun : Transform;

var currDist = 0.5; 
var minDist = 1.0;  // Minimum distance from the previous planet
var maxDist = 2.5;

var count = 9; 

function Start() {
	PlacePlanets();
}

function PlacePlanets() {

	for (var i = 0; i < count; i++) {
		currDist = currDist + Random.Range(minDist, maxDist);
		var v3 = Vector3.right * currDist;
		//v3 = Quaternion.AngleAxis(Random.Range(0.0, 360.0), Vector3.forward) * v3;
		v3 += sun.position;
		
		var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
		go.transform.position = v3;
	}
}

The code randomly spreads the planets out along a vector and then rotates them to an arbitrary angle around the sun. ‘minDist’ and ‘maxDist’ control the minimum and maximum distance one planet may be from another. Note the initialization of ‘currDist’ to a value other than zero is to make sure the first planet was not too close to the sun.