- Home /
How do I implement delays in my code?
Ok so basically, I've been trying to find a solution for my problem for a day now, and I tried my best to find out stuff about coroutines, but despite my numerous attempts, I still didn't manage to implement them in this script. May someone help me to delay the next event for 2 seconds everywhere where the //delay comments are?
void Update()
{
GameObject NPC1 = GameObject.Find("MainNPC1");
CheckIfInCircle NPC1Script = NPC1.GetComponent<CheckIfInCircle>();
GameObject NPC2 = GameObject.Find("Main NPC2");
CheckIfInCircle NPC2Script = NPC2.GetComponent<CheckIfInCircle>();
GameObject NPC3 = GameObject.Find("Main NPC3");
CheckIfInCircle NPC3Script = NPC3.GetComponent<CheckIfInCircle>();
if(NPC1Script.IsInCircle&&NPC2Script.IsInCircle&&NPC3Script.IsInCircle){
//delay
MainCamera.SetActive(false);
CameraN1.SetActive(true);
//delay
CameraN1.SetActive(false);
CameraN2.SetActive(true);
//delay
CameraN2.SetActive(false);
CameraN3.SetActive(true);
//delay
CameraN3.SetActive(false);
CameraPanorama.SetActive(true);
//delay
SceneManager.LoadScene(2);
}
}
Answer by Chris333 · Apr 10, 2019 at 07:34 AM
Untested
You have to be aware that you are calling StartCoroutine multiple times when your if-condition returns true over a longer time (more than one frame) because you calling it inside Update().
If you want to fix that behaviour you need to introduce a helper variable which stores if you are already running the coroutines in the current frame.
private bool isCoroutineRunning;
void Update()
{
GameObject NPC1 = GameObject.Find("MainNPC1");
CheckIfInCircle NPC1Script = NPC1.GetComponent<CheckIfInCircle>();
GameObject NPC2 = GameObject.Find("Main NPC2");
CheckIfInCircle NPC2Script = NPC2.GetComponent<CheckIfInCircle>();
GameObject NPC3 = GameObject.Find("Main NPC3");
CheckIfInCircle NPC3Script = NPC3.GetComponent<CheckIfInCircle>();
if (NPC1Script.IsInCircle && NPC2Script.IsInCircle && NPC3Script.IsInCircle && !isCoroutineRunning)
{
isCoroutineRunning = true;
//delay
StartCoroutine(DelayCameraActivation(2, MainCamera, CameraN1));
//delay
StartCoroutine(DelayCameraActivation(4, CameraN1, CameraN2));
//delay
StartCoroutine(DelayCameraActivation(6, CameraN2, CameraN3));
//delay
StartCoroutine(DelayCameraActivation(8, CameraN3, CameraPanorama));
//delay
StartCoroutine(DelaySceneLoad(10, 2));
}
}
IEnumerator DelayCameraActivation(float delay, GameObject camera1, GameObject camera2)
{
yield return new WaitForSeconds(delay);
camera1.SetActive(false);
camera2.SetActive(true);
}
IEnumerator DelaySceneLoad(float delay, int sceneIndex)
{
yield return new WaitForSeconds(delay);
SceneManager.LoadScene(sceneIndex);
isCoroutineRunning = false;
}
Starting multiple instances of a coroutine is not good practice if you can get it done in one. You are starting 5 separate threads at the same time (5 x as much processing) to accomplish a simple task that can be done in one.
Coroutines does not run in other threads..... Even if you call a thousand coroutines, they will run in the main thread used by Unity.
You got me there, it would be better said to say "5 separate processes", which is 5 times the needed for the first 2 seconds anyway, then 4x for the next 2 seconds. Just wanted to mention it for optimization
Answer by highpockets · Apr 10, 2019 at 07:40 AM
Ok, I think maybe you thought if you had a coroutine it would stop at the line where you started the coroutine until it was finished which is not the case. Here you go:
bool inCoroutine = false;
void Update()
{
GameObject NPC1 = GameObject.Find("MainNPC1");
CheckIfInCircle NPC1Script = NPC1.GetComponent<CheckIfInCircle>();
GameObject NPC2 = GameObject.Find("Main NPC2");
CheckIfInCircle NPC2Script = NPC2.GetComponent<CheckIfInCircle>();
GameObject NPC3 = GameObject.Find("Main NPC3");
CheckIfInCircle NPC3Script = NPC3.GetComponent<CheckIfInCircle>();
if(NPC1Script.IsInCircle&&NPC2Script.IsInCircle&&NPC3Script.IsInCircle&&!inCoroutine){
inCoroutine = true;
StartCoroutine(CameraDance());
}
}
int state = 0;
IEnumerator CameraDance(){
while(state < 5){
yield return new WaitForSeconds(2.0f);
switch(state){
case 0:
MainCamera.SetActive(false);
CameraN1.SetActive(true);
break;
case 1:
CameraN1.SetActive(false);
CameraN2.SetActive(true);
break;
case 2:
CameraN2.SetActive(false);
CameraN3.SetActive(true);
break;
case 3:
CameraN3.SetActive(false);
CameraPanorama.SetActive(true);
break;
case 4:
SceneManager.LoadScene(2);
break;
}
state = state + 1;
}
state = 0;
inCoroutine = false;
}
I also suggest that you do this as well:
GameObject NPC1;
CheckIfInCircle NPC1Script;
GameObject NPC2;
CheckIfInCircle NPC2Script;
GameObject NPC3;
CheckIfInCircle NPC3Script;
Start(){
NPC1 = GameObject.Find("$$anonymous$$ainNPC1");
NPC1Script = NPC1.GetComponent<CheckIfInCircle>();
NPC2 = GameObject.Find("$$anonymous$$ain NPC2");
NPC2Script = NPC2.GetComponent<CheckIfInCircle>();
NPC3 = GameObject.Find("$$anonymous$$ain NPC3");
NPC3Script = NPC3.GetComponent<CheckIfInCircle>();
}
Because using GameObject.Find() and GetComponent() is quite unoptimized and you’re doing it every frame.
Answer by misher · Apr 10, 2019 at 08:03 AM
Launch delays within Update() loop is not an optimal thing, you should split your logic in these: 1. a trigger, 2. an action with delays. You should also handle the case for when you trigger the action while it is already execution, so you need to decide to stop it and restart or ignore it or something else, but for sure not to launch actions multiple times.
As for the trigger, there are colliders in unity that you can set up to be as triggers, so you don't need to check it in update.
Your answer

Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
adding a delay to shooting 2 Answers
Renderer on object disabled after level reload 1 Answer
check alpha of gameObject C# 3 Answers