Problems with arrays

I’m running into a problem with an array where I can only check a condition (in this case, a randomly generated position) against a single element when I want to check against all the positions in the array.

For some context: every time the spawn function is called, I am going to instantiate two types of objects. The positions of both objects will be random, but must be at least a certain distance away from the other object and all instances of the Type_1 object that came before them. There will only be a single instance of the Type_2 object active at a time, but the Type_1 object will be limited to a set amount. When that maximum is hit, the oldest Type_1 object will be destroyed and a new object will be spawned.

Am I far off from doing what I want to (aside from the aforementioned problem)? I know that randomly checking positions could result in some wasted cycles, but because the total (I’m going to limit it to about 20-30), I don’t think it will cause any noticeable framerate issues.

Thanks.

var Collectable_Type_1: GameObject;

var Collectable_Type_2: GameObject;
var Type_1: GameObject[];
var MyPositions: Vector2[];
var Temporary: Vector2;
var Current: int;
var Placeholder: GameObject;

function Update(){
    if(Input.GetKeyDown (KeyCode.Space))
        Spawn();
}

function Spawn() {
Destroy(Placeholder);
    if(Current <= MyPositions.Length){
        for (var i : int = 0; i < MyPositions.length; i++){
            Temporary.x = Random.Range(-5f,5f);   
            Temporary.y = Random.Range(-5f,5f);   
            if(Vector2.Distance(Temporary,MyPositions[i]) <= 1.5f){
                i--;
            }
        }
        MyPositions[Current] = Temporary;
        var spawned_1 : GameObject = Instantiate(Collectable_Type_1, MyPositions[Current], transform.rotation);
        Type_1[Current] = spawned_1;

        for (var j : int = 0; j < MyPositions.length; j++){
            Temporary.x = Random.Range(-5f,5f);   
            Temporary.y = Random.Range(-5f,5f);   
            if(Vector2.Distance(Temporary,MyPositions[j]) <= 1.5f){
                j--;
            }
        }
        MyPositions[Current] = Temporary;
        var spawned_2 : GameObject = Instantiate(Collectable_Type_2, MyPositions[Current], transform.rotation);       
        Placeholder = spawned_2;
        Current += 1;       
    }
   
    if(Current == MyPositions.Length){
        for (var k : int = 0; k < Type_1.length-1; i++){
            Type_1[k-1] = Type_1[k];
        }
        Destroy(Type_1[Type_1.length]);
        Current -= 1;
        Spawn();
    }   
}
        for (var i : int = 0; i < MyPositions.length; i++){
            Temporary.x = Random.Range(-5f,5f); 
            Temporary.y = Random.Range(-5f,5f); 
            if(Vector2.Distance(Temporary,MyPositions[i]) <= 1.5f){
                i--;
            }
        }
//...

This chunk of code seems problematic based on your requirements.

You’re getting another random position for your Temporary on each iteration when the new random position may not respect the same condition as the old random position.

The easiest [but maybe not most optimal] solution would be to start the entire loop over if you run into a condition where Temporary is not the minimum distance away from the position at some MyPositions’ value. However, I wouldn’t use just a for loop but a while loop with a nested for loop. I’m not really up to speed on Javascript, so I’ll do it in CSharp syntax but hopefully the point is conveyed properly:

bool notFinished;
int currentIteration = 0; // safety net - remove if its not needed
int maxIterations = 5000; // safety net - adjust to your needs, remove if its not needed

do
{
    // get our random position
    Temporary.x = Random.Range(-5, 5f);
    Temporary.y = Random.Range(-5, 5f);
    notFinished = false; // assume the position is good until proven otherwise

    // compare this position against all positions currently in the list
    // we only need to check up to the current value if current resembles the number of items actually in the list
    for(int i = 0; i < Current && i < MyPositions.Length; i++)
    {
        if(Vector2.Distance(Temporary, MyPositions[i]) <= 1.5f)
        {
            notFinished = true; // we have to try again since our random position doesn't satisfy the condition
            break; // break out of the nested for loop
        }
    }
    currentIteration++; // safety net - remove if its not needed
}while(notFinished && currentIteration < maxIterations); // try again if we're not done

notFinished is assigned to be false, under the assumption that the position generated is a good one. The moment you run into a position that doesn’t satisfy the minimum distance condition, notFinished becomes true and you start the iteration over. This process will repeat until you find one [or until currentIteration is no longer less than maxIterations]

Notice also that since the value of Current is the number of items currently in the list, you really only need to check up to but not including the Current value.

Ignore the iteration checks if you don’t need them. I’m slightly suspicious that you may run out of valid positions at some point with such a small range, but that’s only because I’m used to defensive coding especially in Unity where an infinite loop can lock up the application.

I see quite a few other potentially problematic portions of your code, but I’m withholding my opinion since I don’t remember everything about Javascript syntax and its possible that you can get away with doing certain things in Javascript as opposed to C#