You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity C#协程时间显示异常:Checkpoint触发后后台更新但UI不刷新

Unity协程计时与分数追踪UI同步问题

我用Unity C#协程实现了计时和分数追踪功能:每10秒更新分数并播放音效,每6秒播放另一款音效,时间归零时触发游戏结束,这部分功能正常。但碰撞Checkpoint时,明明已经触发碰撞(控制台输出已验证),Debug显示后台currentTime确实增加了5秒,可UI上的时间显示始终没同步更新。

相关代码

Checkpoint触发代码

private void OnTriggerEnter(Collider other)
{
    print("Hit checkpoint");
    PlayerPrefs.SetInt("CheckPointHit", 1);
    gameObject.SetActive(false);
}

协程计时代码

IEnumerator LoseTime()
{
    while (true)
    {
        yield return new WaitForSeconds(1);
        currentTime--;

        if (currentTime % 10 == 0)
        {
            currentScore -= SCORE_INCREMENT;
            GameObject.FindGameObjectWithTag("MainCamera").GetComponent<AudioSource>().PlayOneShot(scoreSound);
        }
        if (currentTime % 6 == 0)
        {
            GameObject.FindGameObjectWithTag("MainCamera").GetComponent<AudioSource>().PlayOneShot(explosionSound);
        }

        if (PlayerPrefs.HasKey("CheckPointHit"))
        {
            if (PlayerPrefs.GetInt("CheckPointHit") == 1)
            {
                currentTime += TIME_INCREMENT;
                GameObject.FindGameObjectWithTag("MainCamera").GetComponent<AudioSource>().PlayOneShot(checkpointSound);
                PlayerPrefs.SetInt("CheckPointHit", 0);
                Debug.Log("Collided");
                Debug.Log(currentTime);
            }
        }

        if (currentTime <= 0)
            break;

        if (gameEnd == true)
            break;
    }

    GameOver();
}

UI更新函数(在Update中调用)

private void UpdateLabels()
{
    tmScore.text = "Score: " + currentScore;
    tmTimeLeft.text = "Time Left: " + currentTime; 
}

问题原因与修复方案

核心问题

  1. 用PlayerPrefs传递临时状态完全没必要,它是持久化存储,存在IO延迟和帧同步问题,导致协程读取状态不及时
  2. 协程修改currentTime后,依赖Update帧更新UI,存在1秒左右的显示延迟

具体修复步骤

  1. 替换PlayerPrefs为直接调用方法
    在计时脚本中新增公开方法,直接处理Checkpoint的时间增加:

    public void AddCheckpointTime()
    {
        currentTime += TIME_INCREMENT;
        // 提前缓存AudioSource,避免重复查找
        cameraAudio.PlayOneShot(checkpointSound);
        // 立刻更新UI,不用等下一帧Update
        UpdateLabels();
        Debug.Log("Added checkpoint time: " + currentTime);
    }
    

    修改Checkpoint触发代码,直接调用上述方法:

    private void OnTriggerEnter(Collider other)
    {
        print("Hit checkpoint");
        // 找到计时脚本(假设脚本挂载在玩家对象上)
        TimeManager timeManager = other.GetComponent<TimeManager>();
        if(timeManager != null)
        {
            timeManager.AddCheckpointTime();
        }
        gameObject.SetActive(false);
    }
    
  2. 移除协程中的PlayerPrefs逻辑
    删除协程里所有和PlayerPrefs相关的代码块,避免重复处理时间增加逻辑。

  3. 优化音效查找逻辑
    在脚本Awake阶段缓存AudioSource,避免每帧重复查找:

    private AudioSource cameraAudio;
    
    void Awake()
    {
        cameraAudio = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<AudioSource>();
    }
    

    之后协程里的音效播放直接用缓存的cameraAudio即可。

  4. 协程内修改时间后即时更新UI
    在协程每次修改currentTime后,直接调用UpdateLabels(),确保UI和后台数据同步:

    currentTime--;
    UpdateLabels(); // 即时更新UI
    

内容的提问来源于stack exchange,提问作者Abdullah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 20:15:37