我可以创建倒数计时器而不将其放入更新功能吗?

时间:2015-08-09 13:39:33

标签: c# unity3d

我有一个倒计时脚本,我想传递一些参数,但我只知道如何在Update函数中使用计时器,而Update不接受参数。如何在不使用Update的情况下实现此目的?这是一种正确的方法吗?

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class CountdownTimer : MonoBehaviour
{
    float seconds;
    float minutes;
    public Text timerText;

    public void startTimer(float m, float s)
    {
        minutes = m;
        seconds = s;

        Update ();
    }

    public void Update () 
    {
        if(seconds <= 0)
        {
            seconds = 59;

            if(minutes >= 1)
            {
                minutes --;
            }
            else
            {
                minutes = 0;
                seconds = 0;

                // Show the time in whole seconds, "f0" removes decimal places
                timerText.text = seconds.ToString("f0");
            }
        }
        else
        {
            seconds -= Time.deltaTime;
        }

        if (Mathf.Round (seconds) <= 9)
        {
            timerText.text = seconds.ToString("f0");
        }
    }
}

3 个答案:

答案 0 :(得分:2)

如果您确实需要随时访问计时器的状态,那么类似的东西(尽管代码更清晰,逻辑更简单,请参阅注释中的秒和分钟的提示)是可以的。基本上,累积增量时间以查看自计时器启动以来已经过了多少。

如果你只需要等到计时器结束,那么还有Invoke

public class MyTimer : MonoBehaviour
{
      public float Interval;
      //Some events go here, maybe, to be fired when the timer changes states?

      public void Restart()
      {
           CancelInvoke("Finished"); //In case it's already running.
           Invoke("Finished", Interval); //Calls Finished() Interval seconds from now.
      }

      public void Finished()
      {
           //Fire your events.
      }
}

您也可以选择每隔X秒触发类似Tick()方法的内容,以便能够访问当前经过的时间,但在这种情况下,我会抛弃协同程序并像您一样累积增量时间。

答案 1 :(得分:0)

补充Alex M.的答案,还有InvokeRepeating方法,类似于Invoke,但重复调用目标方法。您可以像这样使用它:

void Start() 
{
    InvokeRepeating("Tick", 0f, 1.0f);
}

private void Tick() 
{
   // do some stuff here every second, e.g. accumulate time in some variable
}

InvokeRepeating的第二个参数是第一次调用Tick的延迟,第三个参数是调用Tick的重复周期。

如果您想将参数插入到重复调用的方法(例如每X秒),则需要查找Coroutines。它们可以像这样使用:

void Start()
{
    StartCoroutine(DoStuffRepeatedly(float param1, bool param2,..., repeatRate));
}

private IEnumerator DoStuffRepeatedly(float param1, bool param2,..., repeatRate) {
    while(someCondition) {
        // do some stuff here
        yield return new WaitForSeconds(repeatRate);
    }
}

答案 2 :(得分:0)

我以这种方式实现了我需要做的事情:

public class GameSetup : MonoBehaviour 
{
    void Start()
    {       
        prevMousePosition = Input.mousePosition;
    }

    void Update()
    {
        if(Input.anyKeyDown || Input.mousePosition != prevMousePosition)
        {
            StartGameTimer();
            timeOutWarning.SetActive(false);
        }
        prevMousePosition = Input.mousePosition;
    }

    void StartGameTimer()
    {
        CancelInvoke ();
        Invoke ("ShowRestartWarning", timeUntilRestartWarning);
    }

    void ShowRestartWarning()
    {
        GameObject gameController = GameObject.FindGameObjectWithTag("gc");                 // First, find the GameObject
        CountdownTimer countdownTimer = gameController.GetComponent<CountdownTimer>();      // Then, access the Script in the GameObject
        countdownTimer.startTimer(countdownLength);                                         // Finally, call the Script method                                                      

        timeOutWarning.SetActive(true);
        CancelInvoke ();
        Invoke ("RestartGame", countdownLength);
    }

    void RestartGame()
    {
        Application.LoadLevel(Application.loadedLevel);
        Debug.Log("Game Restarted");
    }
}

public class CountdownTimer : MonoBehaviour
{
    float seconds;
    public Text timerText;

    public void startTimer(float s)
    {
        seconds = s;
        Update ();
    }

    public void Update () 
    {
        seconds -= Time.deltaTime;
        timerText.text = seconds.ToString("f0");
    }
}