Coroutine beginner
Hi there,
First time C# coder here. I was curious if someone could point to me how to start a coroutine at a specific time in the game. I'm looking everywhere but fail to understand how to do it. I stumbled on code such as the following, but it doesn't work, Unity comes back with a host of errors in the Console. All I really want to do is StartCoroutine after x seconds from the beginning of the game.
void Start(){
Invoke(2.0f, "MyMethod");
StartCoroutine(Delay(2.0f,MyMethod))
}
void MyMethod(){Debug.Log("Call");}
IEnumerator Delay(float timer, Action action){
while(timer > 0f){
timer-=Time.deltaTime;
yield return null;
}
if(action != null){
action();
}
}
source: https://unitygem.wordpress.com/coroutine-usage-invoke-delay/
Thank you for your time, I hope I was succinct enough.
Answer by TBruce · Aug 27, 2016 at 06:14 PM
This fixes your errors
void Start()
{
Invoke("MyMethod", 2.0f);
StartCoroutine(Delay(2.0f, MyMethod));
}
void MyMethod()
{
Debug.Log("Call");
}
IEnumerator Delay(float timer, Action action)
{
while(timer > 0f)
{
timer-=Time.deltaTime;
yield return null;
}
if(action != null)
{
action();
}
}
And you can get more information about coroutines by checking the documentation out
Taken from the StartCoroutine documentation page -
The execution of a coroutine can be paused at any point using the yield statement. The yield return value specifies when the coroutine is resumed. Coroutines are excellent when modelling behaviour over several frames. Coroutines have virtually no performance overhead. StartCoroutine function always returns immediately, however you can yield the result. This will wait until the coroutine has finished execution.
The IEnumerator allows the program to yield things like the WaitForSeconds function, which lets you tell the script to wait without hogging the CPU
Thanks a lot for your answer $$anonymous$$avina. I should have shared my code to clarify things.
$$anonymous$$y script:
public GameObject Box1;
public Vector3 spawnValues;
public int boxCount;
public float spawnWait;
void Start ()
{
StartCoroutine (Box1Waves ());
}
IEnumerator Box1Waves ()
{
while (true)
{
for (int i = 0; i < boxCount; i++)
{
Vector3 spawnPosition = new Vector3 (spawnValues.x, spawnValues.y, spawnValues.z);
Quaternion spawnRotation = Quaternion.identity;
Instantiate (BreadBox1, spawnPosition, spawnRotation);
yield return new WaitForSeconds (spawnWait);
}
}
}
Ultimately I just want to start the Coroutine (Box1Waves()) 20 seconds after I press play. Right now it fires up right away. I'm basically building a sequence of box on rails for a factory and they need to follow one another. I haven't been able to figure out much from the documentation on that level. I saw that someone was able to pass a time variable inside the parentheses (ie: Start Coroutine Box1Waves(2.0F));
) but Unity gives me error like
Assets/Scripts/PackagingBreadBox1Spawn.cs(13,33): error CS1501: No overload for method `Box1Waves' takes `1' arguments
Assets/Scripts/PackagingBreadBox1Spawn.cs(13,17): error CS1502: The best overloaded method match for `UnityEngine.$$anonymous$$onoBehaviour.StartCoroutine(System.Collections.IEnumerator)' has some invalid arguments
Assets/Scripts/PackagingBreadBox1Spawn.cs(13,17): error CS1503: Argument `#1' cannot convert `object' expression to type `System.Collections.IEnumerator'
Not sure if I'm being sufficient in my explanations, posting on forums is also quite new to me. :)
Thanks again for all your help and patience.
This fixes your code
public GameObject Box1; // BreadBox1;
public Vector3 spawnValues = Vector3.zero;
public int boxCount;
public float spawnWait = 20; // default to 20 seconds
void Start ()
{
// ensure that we can start the coroutine
if ((Box1 != null) && (boxCount >0))
{
StartCoroutine (Box1Waves ());
}
}
IEnumerator Box1Waves ()
{
// wait for 20 seconds before continuing
yield return new WaitForSeconds (spawnWait);
// note: this is an endless loop so either break at the end of the for loop (or remove while portion of code)
// or instantiate boxCount more times
while (true)
{
for (int i = 0; i < boxCount; i++)
{
Instantiate (Box1, spawnValues, Quaternion.identity);
yield return new WaitForSeconds (spawnWait);
}
yield return 0;
break; // doing this only instantiates boxCount number of object
}
}
I removed a few lines because they were redundant. I also set some defaults for you.
I am not sure what you are going for but the code above will instantiate all objects in the same position. If you want to randomly instantiate your objects you can do something like this
public GameObject Box1; // BreadBox1;
public int boxCount;
public float spawnWait = 20; // default to 20 seconds
public Vector2 $$anonymous$$Point = new Vector2(-20, -4);
public Vector2 maxPoint = new Vector2(20, 4);
void Start ()
{
// ensure that we can start the coroutine
if ((Box1 != null) && (boxCount >0))
{
StartCoroutine (Box1Waves ());
}
}
IEnumerator Box1Waves ()
{
// wait for 20 seconds before continuing
yield return new WaitForSeconds (spawnWait);
// note: this is an endless loop so either break at the end of the for loop (or remove while portion of code)
// or instantiate boxCount more times
while (true)
{
for (int i = 0; i < boxCount; i++)
{
Vector3 spawnPosition = new Vector3 (Random.Range($$anonymous$$Point.x, maxPoint.x), Random.Range($$anonymous$$Point.y, maxPoint.y), 0); // you can randomize the Y value as well if needed
Instantiate (Box1, spawnPosition, Quaternion.identity);
yield return new WaitForSeconds (spawnWait);
}
yield return 0;
break; // doing this only instantiates boxCount number of object
}
}
I just got around to it. It works beautifully well. Putting a yield before the while loop did the trick. I indeed needed to spawn at the same location (the boxes are endlessly co$$anonymous$$g out of a box making machine).
Thank you quite a bunch $$anonymous$$avina. I appreciate the professionalism and the help. :)
@armadea I am happy that this is working for you.
There is no need to add additional comments. This answer and the as well as the rest of the conversation will be marked for historical purposes.
All that is necessary is for you to click the "Accept" button above to accept the answer? Thank you and good luck!