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; }
问题原因与修复方案
核心问题
- 用
PlayerPrefs传递临时状态完全没必要,它是持久化存储,存在IO延迟和帧同步问题,导致协程读取状态不及时 - 协程修改
currentTime后,依赖Update帧更新UI,存在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); }移除协程中的PlayerPrefs逻辑
删除协程里所有和PlayerPrefs相关的代码块,避免重复处理时间增加逻辑。优化音效查找逻辑
在脚本Awake阶段缓存AudioSource,避免每帧重复查找:private AudioSource cameraAudio; void Awake() { cameraAudio = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<AudioSource>(); }之后协程里的音效播放直接用缓存的
cameraAudio即可。协程内修改时间后即时更新UI
在协程每次修改currentTime后,直接调用UpdateLabels(),确保UI和后台数据同步:currentTime--; UpdateLabels(); // 即时更新UI
内容的提问来源于stack exchange,提问作者Abdullah
相关产品推荐
相关产品推荐

