我可以创建一个倒计时计时器,而不把它放在更新功能

本文关键字:新功能 更新 计时器 创建 倒计时 一个 我可以 | 更新日期: 2023-09-27 18:07:00

我有一个倒计时脚本,我想传递几个参数,但我只知道如何在更新函数中使用计时器,更新不接受参数。如何在不使用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");
        }
    }
}

我可以创建一个倒计时计时器,而不把它放在更新功能

如果您确实需要随时访问计时器的状态,那么类似的东西(尽管代码更简洁,逻辑更简单,参见我在评论中关于秒和分钟的提示)是可以的。基本上,累积增量时间来查看从计时器开始以来已经过去了多少时间。

如果你只需要等待计时器完成,那么还有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()方法来访问当前经过的时间之类的东西,但在这种情况下,我将放弃协程并像您一样累积增量时间。

补充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秒),你需要查找协程。它们可以这样使用:

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

我通过这种方式完成了我需要做的事情:

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