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);
    }
}

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;
    }

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;
}

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.