简体   繁体   中英

Unity C# timer should trigger function every 1.5 min but doesn't

I'm trying to write a script that turns all lights off after 1.5 minutes for 10 seconds, then turns them back on.
Right now, it seems like the timer is getting bypassed. I realize that the reason for this is probably because the time will never be exactly 90 or so.
That being said, I have no idea how to get the result I want.

I thought of using InvokeRepeating instead (as commented out) but then that would mean that the lights would be off longer every time.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LightsTimerTrigger : MonoBehaviour {
    private GameObject[] allLights;
    private float time = 0.0f;
    private float secondTimer = 0.0f;

    void Start () {
        // Create array of lights 
        allLights = GameObject.FindGameObjectsWithTag("riddleLights");

        //InvokeRepeating("lightsOn", 60.0f, 120.0f);
        //InvokeRepeating("lightsOff", 60.10f, 120.10f); // Exponential
    }

    // Update is called once per frame
    void Update () {
        time += Time.deltaTime;

        if(time%90 == 0)
        {
            secondTimer = time;
            lightsOff();
            Debug.Log("Lights off");
        }

        if (time == secondTimer + 10)
        {
            // Turn lights back on after 10 seconds
            lightsOn();
            Debug.Log("Lights back on");
        }
    }

    void lightsOff()
    {
        foreach (GameObject i in allLights)
        {
            i.SetActive(false);
        }
    }

    void lightsOn()
    {
        foreach (GameObject i in allLights)
        {
            i.SetActive(true);
        }
    }
}
 if(time%90 == 0) 

This will (almost certainly) never be true.

What happens if the time is 90.000000001? Well, divide off the 90 part and check if(0.000000001 == 0) which is false.

You should correct your code thusly:

if(time >= 90) {
    time -= 90;
    //the rest of your code
}

You'll have to do something similar for your 10 second delay.

The coroutine option:

void Start () {
    //existing code
    StartCoroutine(FlickerLights());
}

IEnumerator FlickerLights() {
    while(true) {
        yield return new WaitForSeconds(90);
        lightsOff();
        Debug.Log("Lights off");
        yield return new WaitForSeconds(10);
        lightsOn();
        Debug.Log("Lights back on");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM