- Home /
Delay before any action
So... Hi, I was searching for this in some of the Unity Answers, but I couldn't find, what I needed... So I need something, that will delay ANY action, like:
void Update()
{
object1.setActive(false);
//delay
object2.setActive(true);
}
This was an example. Here is another one:
void Update()
{
sound1.Play();
//delay
sound2.Play();
//delay
object.setActive(true);
}
Answer by pslattery · Aug 21, 2017 at 08:01 PM
Have you looked at Coroutines? This is exactly what they're for.
Update is designed to be executed, start to finish, within one frame (this is actually the function that defines what a frame is). This means that it doesn't make much sense to have Update span multiple frames.
What you want to do is have update start a Coroutine that handles delaying these sounds. This does mean you have to manage that Coroutine so you don't start a new one every frame, but this is pretty standard.
So you're code would look like:
Coroutine co_PlaySounds;
bool isPlayingSounds;
void Awake() {
isPlayingSounds = false;
}
void Update () {
if (!isPlayingSounds) {
if (co_PlaySounds != null)
StopCoroutine (co_PlaySounds);
co_PlaySounds = StartCoroutine (PlaySounds (1.5f));
}
}
IEnumerator PlaySounds (float delay) {
isPlayingSounds = true;
sound1.Play ();
yield return new WaitForSeconds (delay);
sound2.Play ();
yield return new WaitForSeconds (delay);
sound3.Play ();
isPlayingSounds = false;
}
Thank you for your answer! But I already figured it out... I used Invoke and delay.`Invoke("part2" //time )
void part2(){ object setActive(false); }`
I'm glad you solved your problem, but using Invoke isn't exactly a great way to accomplish this.
Invoke relies on the name of your function never changing. And if you do change it, you have to make sure to change it in all the places you've called Invoke on it. Its much better practice to rely on the compiler to call these things out, which it will only do if you're calling the actual function, not just using its name.
Enumerators are really powerful, and, even if you don't use them this time, I'd recommend learning how to use them for future problems.
Good luck!
Answer by Wi8games · Aug 21, 2017 at 08:08 PM
Using:UnityEngine.IEnumerator;
Void Update () { StartCoroutine(delay()); }
IEnumerator delay () { sound1.Play(); yield return new WaitForSeconds(1); sound2.Play(); Yield return new WaitForSeconds(1); Object.setActive(true);
}
This will wait for 1 second
Thank you for your answer! But I already figured it out... I used Invoke and delay.`Invoke("part2" //time )
void part2(){ object setActive(false); }`
Answer by Dibbie · Aug 21, 2017 at 08:12 PM
It sounds to me that what your looking for is a Coroutine. They are able to do just that, using some of the following: WaitForSecondsRealtime(float); WaitUntil (() => (delegate) ); WaitForEndOfFrame(); and a few others, including simply null.
It is used like this:
yield return new WaitForSecondsRealtime(3f); //will wait 3 seconds before continuing this loop.
In your example, you may use one like this:
IEnumorator DelayStuff()
{
while(object.activeSelf == false)
{
sound1.Play();
yield return new WaitForSecondsRealtime(3f);
//3 seconds later...
sound2.Play();
yield return new WaitForSecondsRealtime(3f);
//3 seconds later...
object.setActive(true);
}
}
Though since this is for audio, I would suggect maybe instead of specifying 3f, you could specify something like yield return new WaitForSecondsRealtime(sound1.length);
so when that clip is done playing, itll move on - or even yield return new WaitUntil(() => sound1.isPlaying == false)
If you really wanted to use Update for this, I would first suggest to use LateUpdate or FixedUpdate as their more accurate and fixed to approximately 1 second, far better than Update is. Then I would suggest to create a public "time" variable, you can use and a "max value" to know when to stop. Something like:
public float timePassed = 0;
public float waitTime = 3f;
void Update(){
if(timePassed >= waitTime){
sound1.Play();
waitTime = 3f;
timePassed = 0f;
sound2.Play();
waitTime = 3f;
timePassed = 0f;
object.setActive(true);
timePassed = waitTime; //finished.
}
else {
timePassed += Time.deltaTime;
}
}
Which as you can see, is a little bit more messy than a coroutine, given, it can be cleaned up a bit by creating a function to call instead thatll do that code, but it sounds like a coroutine will do what you want a lot better, I would suggest to look into them a little more - and try to avoid making infinite loops (so while(true){} for example)
Thank you for your answer! But I already figured it out... I used Invoke and delay.`Invoke("part2" //time )
void part2(){ object setActive(false); }`
Your answer
Follow this Question
Related Questions
Add Delay to Moving Platform 1 Answer
creating a timed function 3 Answers
How Can I enable and then disable a light in unity after a certain time? 1 Answer
Unity how to find load time? 1 Answer
Simple Timer 2 Answers