Unity开发中PlayerPrefs无法正确持久化存储Money数值问题
问题原因
你的金币存储失效是4个核心逻辑错误导致的:
- 没有在脚本初始化阶段读取本地存储的金币值赋值给内存变量
money:int属于值类型,类实例化后默认初始值为0,每次游戏启动money都会从0开始计数。 - 金币读写逻辑顺序完全写反:在
play()方法中,你先读取本地存储的金币显示到UI,紧接着判断内存中初始值为0的money和本地存储值不一致时,直接把0写入本地存储,直接覆盖了之前攒的所有金币数据。 - 金币变动时没有同步UI、没有主动触发存储落盘:
IncreaseScore()方法中只对内存中的money做了自增,没有刷新金币文本显示;调用PlayerPrefs.SetInt()后没有主动调用保存方法,游戏异常退出时可能出现写入失败。 - 读取
money存储值时没有设置默认值,首次启动游戏无对应键值时会出现非预期返回。
修复方案
- 在
Awake()生命周期完成本地数据初始化读取,直接把存储的金币、最高分赋值给对应内存变量,同步初始化UI。 - 删除
play()方法中错误的金币覆盖逻辑,金币是全局累计数据,单局开始时不需要重置、也不允许把初始0值写入存储。 - 修正金币更新逻辑:金币变动时同步刷新UI,游戏结束确认数据无误后再写入存储,写入后主动调用
PlayerPrefs.Save()确保落盘。 - 所有
PlayerPrefs.GetInt()调用都传入默认值,避免首次启动异常。
修复后的完整代码如下:
using TMPro; using UnityEngine; public class GameManager : MonoBehaviour // 原代码漏写类声明,可根据你的实际类名修改 { public GameObject playButton; public GameObject Gameover; public GameObject ShopMenu; public Player player; public TMP_Text scoreText; public TMP_Text MoneyText; public TMP_Text highScore; public int score; public int money; private void Awake() { Application.targetFrameRate = 60; // 初始化读取本地存储数据 money = PlayerPrefs.GetInt("money", 0); int savedHighScore = PlayerPrefs.GetInt("HighScore", 0); // 初始化UI显示 MoneyText.text = money.ToString(); highScore.text = savedHighScore.ToString(); Pause(); } public void play() { // 单局仅重置当局分数,金币是全局累计数据不重置 score = 0; scoreText.text = score.ToString(); playButton.SetActive(false); Gameover.SetActive(false); ShopMenu.SetActive(false); Time.timeScale = 1f; player.enabled = true; pipes[] pipes = FindObjectsOfType<pipes>(); for (int i = 0; i < pipes.Length; i++) { Destroy(pipes[i].gameObject); } } public void Pause() { Time.timeScale = 0f; player.enabled = false; } public void GameOver() { Gameover.SetActive(true); playButton.SetActive(true); ShopMenu.SetActive(true); // 处理最高分存储 int savedHighScore = PlayerPrefs.GetInt("HighScore", 0); if (score > savedHighScore) { PlayerPrefs.SetInt("HighScore", score); highScore.text = score.ToString(); } // 处理金币存储:当前内存money就是累计总金币,直接写入即可 PlayerPrefs.SetInt("money", money); MoneyText.text = money.ToString(); // 主动触发保存,避免异常退出丢数据 PlayerPrefs.Save(); Pause(); } public void IncreaseScore() { score++; scoreText.text = score.ToString(); money++; // 金币变动同步刷新UI MoneyText.text = money.ToString(); } }
额外注意
- 如果你后续做商店消耗金币的逻辑,记得扣除金币后同步更新
money变量、刷新UI,并且在扣除操作完成后立刻调用PlayerPrefs.SetInt("money", money)和PlayerPrefs.Save(),避免买完东西退游戏出现数据不同步问题。 - 编辑器测试时如果要清空存档数据,可以调用
PlayerPrefs.DeleteAll()方法做临时测试按钮,不要把这个逻辑带到正式发布版本里。
内容的提问来源于stack exchange,提问作者Naffy
相关产品推荐
相关产品推荐

