- Home /
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:
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.
Your English is fine, but nobody can help you unless you post code.
So to be clear, does this behavior happen often, or just occasionally?
Are you placing them all at once or are they added at different times?
Well, it happens randomly but I want to eli$$anonymous$$ate it, and they are placed all at once.
Hey Xentarok, if any of the answers helped you solve your question, could you flagh it as the correct answer? This will help others with similar questions more easily find this one. Thanks!
Answer by robertbu · Jun 01, 2013 at 09:09 PM
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.
Thank you for your anserws, I'm sure I know how to fix this problem now :)
Answer by Memige · Jun 01, 2013 at 08:49 PM
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++;
}
Thank you for your answer, but to clarify: The generation is already in a while loop with random variable which represents the number of planets ( float NumberOfPlanets = Random.Range(1,8)). Anyway, could you please explain the "registering position and checking the result against your registered list" a little bit more? I'd be more than thankfull. And by the way, the position is always diffrent, but the distance from the star is the same.
-Xentarok
Added a second code spinet to showcase exa$$anonymous$$ing just one variable. Have a look at the edit
The idea is you have a list of all the distances that are currently being used, and every time you generate a new one, you check to see if it already exists, If it does, you discard it and generate a new one, until you get a distance not already in your list.
I'm sorry if I'm missing something, but what about when position is just slightly diffrent (like for example 132 and 132.5). In this case you'd still get planets "touching" each other.
And again, thank you for your answers.
-Xentarok
Not a problem :) for close things it gets a little more complicated (but only a little) gimme a sec and I'll add another snipet
Your answer
Follow this Question
Related Questions
Another Random Generation Problem 1 Answer
Spherical Light for Solar System Illumination 0 Answers
Terrain Toolkit - License 0 Answers
Generation Problem c# 0 Answers