从Update调用的Coroutine不生效,IEnumerator无法运行,问题出在哪?
问题根源与修复方案
核心问题
- PlayerPrefs持久化残留:你之前测试时触发过成就,
PlayerPrefs.SetInt("Ach01", 12345)已经把值存在本地了,程序启动时PlayerPrefs.GetInt("Ach01")会直接读出这个旧值,导致ach01Code一开始就是12345。 - Update逻辑冗余:每帧都读取
PlayerPrefs不仅没必要,还会覆盖你在协程里临时设置的ach01Code值。 - 无重复触发防护:没有判断
achActive状态,可能导致协程被多次启动。 - 静态变量未初始化:
ach01Count是static类型,场景重启或对象重建时会保留之前的数值,可能一开始就等于触发阈值5。
修复步骤
- 清理旧的PlayerPrefs数据(测试用,上线前移除):在
Start方法里临时添加代码,清除之前存的成就值。 - 优化变量初始化逻辑:把
ach01Code的读取移到Start,避免每帧重复读取;初始化ach01Count为0,防止静态变量残留。 - 添加重复触发防护:在判断条件里加入
!achActive,避免协程被多次启动。 - 确保PlayerPrefs立即保存:在协程里设置完值后调用
PlayerPrefs.Save()。
修改后的完整代码
using UnityEngine; using UnityEngine.UI; public class AchievementManager : MonoBehaviour { // General Vars public GameObject achNotif; public AudioSource achSound; public bool achActive = false; public GameObject achTitle; public GameObject achText; // Collection Based (01) public GameObject ach01Image; public int ach01Count = 0; // 去掉static,初始化0 public int ach01Trigger = 5; public int ach01Code; private void Start() { // 初始化时读取一次成就状态即可 ach01Code = PlayerPrefs.GetInt("Ach01", 0); // 无键时返回默认值0 // 测试用:清理旧的成就数据,上线前删除 // PlayerPrefs.DeleteKey("Ach01"); // PlayerPrefs.Save(); } private void Update() { // 加!achActive防止重复触发协程 if (ach01Count == ach01Trigger && ach01Code != 12345 && !achActive) { StartCoroutine(Trigger01Ach()); Debug.Log("Achievement Collected!"); } } IEnumerator Trigger01Ach() { achActive = true; ach01Code = 12345; PlayerPrefs.SetInt("Ach01", ach01Code); PlayerPrefs.Save(); // 确保立即写入本地 achSound.Play(); ach01Image.SetActive(true); achTitle.GetComponent<Text>().text = "COLLECTION!"; achText.GetComponent<Text>().text = "Created A Collection Based Achievement"; achNotif.SetActive(true); yield return new WaitForSeconds(7); // Reset UI achNotif.SetActive(false); ach01Image.SetActive(false); achTitle.GetComponent<Text>().text = ""; achText.GetComponent<Text>().text = ""; achActive = false; } // 收集道具时调用此方法 public void CollectItem() { if (ach01Code != 12345) // 已解锁成就就不再计数 { ach01Count++; } } }
额外注意事项
- 确保收集道具的逻辑正确调用
CollectItem()方法,否则ach01Count不会增加。 - 上线前务必移除测试用的
PlayerPrefs.DeleteKey代码,避免清空玩家的成就数据。
内容的提问来源于stack exchange,提问作者Aaron Benson
相关产品推荐
相关产品推荐

