[Solved] Invoke and Arrays to Instantiate at specific times

Hello
I’m a beginner but trying to learn unity C#, and my next challenge is to learn to create Objects at certain time values, sync to a specific music.
So my idea is to first write down these values by checking the time from any Sound editor.
Let’s say my music is 15 seconds long and I want to send my object at 1s,2s,5s,6s,9s,11s

For what i was able to check so far, I need to use Invoke and Arrays (link to the tutorial I’ve seen before writing this)

so Invoke Example is

using UnityEngine;
using System.Collections;

public class InvokeScript : MonoBehaviour
{
    public GameObject target;
  
  
    void Start()
    {
        Invoke ("SpawnObject", 2);
    }
  
    void SpawnObject()
    {
        Instantiate(target, new Vector3(0, 2, 0), Quaternion.identity);
    }
}

and Arrays example is not very usefull here
so my guess to do what I wish to do is something like:

using UnityEngine;
using System.Collections;

public class InvokeScript : MonoBehaviour
{
    public GameObject target;
    int[] myIntArray = {1,2,5,6,9,11};
  
    void Start()
    {      
        for(int i = 0; i < myIntArray.Length; i++)
        {
           Invoke ("SpawnObject", myIntArray[i])
        }

    void SpawnObject()
    {
        Instantiate(target, new Vector3(0, 2, 0), Quaternion.identity);
    }

}

Am I going the good direction here ?
Is there any steps missing to do this right ?
Should I think this differently ?

Thx a lot.

It won’t work as Invoke(…) can’t be called twice on method with same name until it has already invoked. It will overwrite its execution time instead of quering it.

I’d do it as coroutine:

//Assumes myIntArray is sorted so each next element is larger than previous.
IEnumerator SpawnObjects()
{
    int previousNumber = 0;//We remember previous time in this variable. Needed for first element of loop as previous number is not yet available at that time.
    for(int i=0;i<myIntArray.Length;i++)
    {
//Now we wait until next time in array by waiting difference between next time and current.
        yield return new WaitForSeconds(myIntArray[i] - previousNumber);
        previousNumber = myIntArray[i];
        SpawnObject();//The one you wrote in your code snippet.
    }
}

//In code to start it call:
void Start()
{
    StartCoroutine(SpawnObjects());
}

Another way is calling Invoke(“SpawnObject”, ); from SpawnObject, but I don’t think it’s good practice to make methods do what they shouldn’t.

P.S. if you just rename in my SpawnObjects in my code snippet into Start() and remove old Start() it will work too as Start() can be a coroutine.

EDIT: made code a bit more pretty.

1 Like

Thx a lot!
I will look at this (and read it slowly to be sure to understand :).
in the meantime, I succeeded to do something on my side using a Coroutine

        public GameObject pickups;
        public Vector3 spawnValues;
        public int hazardCount;    // should be the total number of values in myIntArray
        public float startWait;       // time before launch
        public float waveWait;     // value before loop from start

        int[] myIntArray = {1,1,8,1,3,1};
// -------------------------------------------------------------------
        void Start ()
        {
            StartCoroutine (SpawnWaves ());
        }

// -------------------------------------------------------------------
        IEnumerator SpawnWaves ()
        {
            yield return new WaitForSeconds (startWait);
            while (true)
            {
                for (int i = 0; i < hazardCount; i++)
                {
                    Vector3 spawnPosition = new Vector3 (spawnValues.x, Random.Range (-spawnValues.y, spawnValues.y), spawnValues.z);
                    Quaternion spawnRotation = Quaternion.identity;
                    Instantiate (pickups, spawnPosition, spawnRotation);
                yield return new WaitForSeconds (myIntArray[i]);
                }
                yield return new WaitForSeconds (waveWait);
            }
        }
    }

It’s working fine, but maybe here,
this might be usefull only if i want this to loop of for spawning infinite elements ?

Any instantiation that’s spreaded in time. It doesn’t matter if it’s limited or infinite. In my case it’s limited, in what you posted it’s infinite. If you remove “while(true)” you’ll make it limited (only 1 wave spawned at all). But it’ll still be spreaded over time.

Thx for the “while(true)” loop reminder, it’s true that it can allow to not repeat if not there :slight_smile: