Unity调用NextLevel时gemsCollected仅短暂增长,无法持久存储数值
解决Unity场景切换时宝石收集数值无法持久化的问题
你当前的代码存在两个核心问题,导致数值无法保留:
- 执行顺序错误:先调用
NextLevel()加载新场景,会直接销毁当前场景的所有对象,后续的gemsCollected++根本没机会执行。 - 变量未做持久化处理:
gemsCollected是普通实例变量,场景切换时脚本所在对象被销毁,变量值自然丢失。
下面提供三种不同场景下的解决方案:
方案1:静态变量(快速实现,适合小型项目)
静态变量属于类本身,不会随实例销毁而消失,只要游戏进程不结束就会保留值。修改代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class gemTaken : MonoBehaviour { public GameObject gem1; public Transform playerNearCheck01; public float playerCheckRadius01; public LayerMask playerLayer; private bool takenByPlayer; // 将变量改为静态类型 public static int gemsCollected; void Update() { Debug.Log(gemsCollected); takenByPlayer = Physics2D.OverlapCircle(playerNearCheck01.position, playerCheckRadius01, playerLayer); if (takenByPlayer) { // 先执行加分,再加载场景 gemsCollected ++; NextLevel(); } } void NextLevel() { SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex +1 ); } }
其他场景要访问这个值时,直接用gemTaken.gemsCollected即可。但静态变量在游戏重启后会重置,若需要永久保存,参考方案3。
方案2:单例模式(规范全局状态管理,适合中大型项目)
创建一个全局状态管理对象,标记为DontDestroyOnLoad,确保场景切换时不被销毁:
- 新建
GameManager脚本:
using UnityEngine; public class GameManager : MonoBehaviour { // 全局单例实例 public static GameManager Instance; public int gemsCollected; void Awake() { // 保证全局只有一个GameManager实例 if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } }
- 修改原
gemTaken脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class gemTaken : MonoBehaviour { public GameObject gem1; public Transform playerNearCheck01; public float playerCheckRadius01; public LayerMask playerLayer; private bool takenByPlayer; void Update() { Debug.Log(GameManager.Instance.gemsCollected); takenByPlayer = Physics2D.OverlapCircle(playerNearCheck01.position, playerCheckRadius01, playerLayer); if (takenByPlayer) { GameManager.Instance.gemsCollected ++; NextLevel(); } } void NextLevel() { SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex +1 ); } }
这种方式可以集中管理所有全局状态(比如生命值、关卡进度等),代码结构更清晰。
方案3:PlayerPrefs(永久保存,重启游戏不丢失)
如果需要关闭游戏后再次打开仍保留收集的宝石数,用PlayerPrefs存储数据:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class gemTaken : MonoBehaviour { public GameObject gem1; public Transform playerNearCheck01; public float playerCheckRadius01; public LayerMask playerLayer; private bool takenByPlayer; private int gemsCollected; void Start() { // 游戏启动时读取本地保存的数值,默认值为0 gemsCollected = PlayerPrefs.GetInt("GemsCollected", 0); } void Update() { Debug.Log(gemsCollected); takenByPlayer = Physics2D.OverlapCircle(playerNearCheck01.position, playerCheckRadius01, playerLayer); if (takenByPlayer) { gemsCollected ++; // 将数值保存到本地 PlayerPrefs.SetInt("GemsCollected", gemsCollected); PlayerPrefs.Save(); NextLevel(); } } void NextLevel() { SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex +1 ); } }
注意:PlayerPrefs适合存储少量非敏感数据,若需要更安全的持久化,可以考虑用文件序列化或Unity官方的Save System。
内容的提问来源于stack exchange,提问作者Elver David Båshus
相关产品推荐
相关产品推荐

