【问题标题】:Unity Timer ResetUnity 定时器重置
【发布时间】:2021-06-10 09:11:44
【问题描述】:

我的游戏中有一个计时器,可以计算直到游戏结束的时间。我不知道如何制作它,所以它只会在菜单场景处于活动状态时重置回 0(构建索引 0)。第二个问题是我不希望它在每次死亡(场景重新加载)后回到 0。你有什么建议吗?

using UnityEngine; 
using UnityEngine.UI; 
using UnityEngine.SceneManagement;

public class Timer : MonoBehaviour { 
public Text TimerText; 
public bool shouldCountTime; 
public float t;

 private void Start()
 {
     if (SceneManager.GetActiveScene().buildIndex != 0)
     {
         shouldCountTime = true;
     }
     else
     {
         shouldCountTime = false;
         t = 0;
     }
     t = Time.deltaTime;
 }
 void Update()
 {
     if (shouldCountTime) {
         t += Time.deltaTime;
     }
     string minutes = ((int)t / 60).ToString();
     string seconds = (t % 60).ToString("f2");
     TimerText.text = minutes + ":" + seconds;
 } 
}

【问题讨论】:

标签: c# unity3d timer


【解决方案1】:

如前所述,您应该将其设为单例(意味着一次只应存在一个实例 - 不是谈论具有公共静态引用的一般(ab)使用;))

并使用DontDestroyOnLoad 以便在场景更改时也保留您的对象,并在重置时使用SceneManager.sceneLoaded 并检查新加载场景的索引,例如

public class Timer : MonoBehaviour 
{ 
    // Make sure this text is also not destroyed
    // e.g. make its entire canvas a child of this object
    public Text TimerText; 
    public bool shouldCountTime; 
    public float t;

    // Singleton Pattern -> make sure only one instance exists in your scene
    private static Timer _instance;

    private void Awake()
    {
        // does another instance already exist?
        if(_instance && _instance != this)
        {
            // if so detroy this one
            Destroy(gameObject);
            return;
        }

        // This is the active instance
        _instance = this;

        // Don't destroy this GameObject when a new scene is loaded
        DontDestroyOnload(gameObject);

        // Attach a callback for every new scene that is loaded
        // It is fine to remove a callback that wasn't added so far
        // This makes sure that this callback is definitely only added once
        // usually I do this only as a kind of convention
        SceneManager.sceneLoaded -= OnSceneLoaded;
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    // Will be called every time a scene is loaded
    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // check the build index
        shouldCountTime = scene.buildIndex != 0;

        // Reset in the main menu
        if(!shouldCountTime)
        {
            Debug.Log("Reset timer", this);
            t = 0;
            TimerText.text = "0:00";
        }
    }

    private void OnDestroy()
    {
        // Even though your object most probably lives during the entire application lifetime
        // again just as a convention always remove callbacks as soon as not needed anymore
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

     void Update()
     {
         // do your calculations only while the value is actually changing
         if (!shouldCountTime) return;

         t += Time.deltaTime;
         var minutes = ((int)t / 60).ToString();
         var seconds = (t % 60).ToString("f2");
         TimerText.text = minutes + ":" + seconds;
     } 
}

如果更改层次结构(例如文本)不是一种选择,而不是参考How to pass data between scenes in Unity 以获取关心价值的替代解决方案。

【讨论】:

  • 计时器应该是一个单独的游戏对象吗?
  • @AndreiPreda 如果您不希望其他东西受到DontDestroyOnLoad 的影响,那么可以!
  • 我刚回家,测试了它,但是当下一个场景加载时它说:“'Text'类型的对象已被破坏,但你仍在尝试访问它。'
  • 是的,当然 .. 看看我在代码中的第一条评论 ^^
猜你喜欢
  • 2021-07-15
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多