Unity多场景游戏时间同步求助:时钟切换场景后重置
Unity 2D RPG跨场景时间同步问题解决
问题根源
你的代码存在两个核心问题导致PlayerPrefs未生效:
- 初始化阶段未从PlayerPrefs加载完整游戏时间,
day变量始终从0开始累加,场景切换后直接重置 - 仅保存了整数天数,丢失了一天内的时间进度(比如上午10点对应的小数部分),导致切换场景后当天时间回到0点
修复方案
方案1:PlayerPrefs永久保存完整时间(推荐)
修改代码,在初始化时加载完整的游戏时间(包含天数和当天进度),用PlayerPrefs保存浮点数类型的完整时间值:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ClockUI : MonoBehaviour { private const float REAL_SECONDS_PER_INGAME_DAY = 60f; private Transform clockHourHandTransform; private Transform clockMinuteHandTransform; public Text dayText; public Text timeText; private float day; // 整数部分为天数,小数部分为当天时间进度 private void Awake() { clockHourHandTransform = transform.Find("hourHand"); clockMinuteHandTransform = transform.Find("minuteHand"); timeText = transform.Find("timeText").GetComponent<Text>(); dayText = transform.Find("dayText").GetComponent<Text>(); // 初始化时读取保存的时间 if (PlayerPrefs.HasKey("GameTime")) { day = PlayerPrefs.GetFloat("GameTime"); } else { day = 0f; // 首次运行默认从第0天开始 } } private void Update() { // 更新游戏时间 day += Time.deltaTime / REAL_SECONDS_PER_INGAME_DAY; // 计算指针旋转角度 float dayNormalized = day % 1f; float rotationDegreesPerDay = 360f; clockHourHandTransform.eulerAngles = new Vector3(0, 0, -dayNormalized * rotationDegreesPerDay); float hoursPerDay = 24f; clockMinuteHandTransform.eulerAngles = new Vector3(0, 0, -dayNormalized * rotationDegreesPerDay * hoursPerDay); // 格式化时间文本 string hoursString = Mathf.Floor(dayNormalized * hoursPerDay).ToString("00"); float minutesPerHour = 60f; string minutesString = Mathf.Floor(((dayNormalized * hoursPerDay) % 1f) * minutesPerHour).ToString("00"); // 格式化天数文本 int currentDay = (int)Mathf.Floor(day); timeText.text = $"{hoursString}:{minutesString}"; dayText.text = $"Day: {currentDay}"; // 保存完整时间到PlayerPrefs PlayerPrefs.SetFloat("GameTime", day); // 可选:显式调用Save确保数据写入磁盘,避免崩溃丢失 // PlayerPrefs.Save(); } // 场景切换或销毁时强制保存 private void OnDestroy() { PlayerPrefs.Save(); } }
方案2:单例持久化(仅运行时跨场景同步)
如果不需要永久保存时间(仅游戏运行期间跨场景同步),可以将时钟对象设为永不销毁的单例:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ClockUI : MonoBehaviour { public static ClockUI instance; // 全局单例实例 private const float REAL_SECONDS_PER_INGAME_DAY = 60f; private Transform clockHourHandTransform; private Transform clockMinuteHandTransform; public Text dayText; public Text timeText; private float day; private void Awake() { // 单例逻辑:避免重复创建 if (instance != null && instance != this) { Destroy(gameObject); return; } instance = this; DontDestroyOnLoad(gameObject); // 跨场景保留对象 clockHourHandTransform = transform.Find("hourHand"); clockMinuteHandTransform = transform.Find("minuteHand"); timeText = transform.Find("timeText").GetComponent<Text>(); dayText = transform.Find("dayText").GetComponent<Text>(); } private void Update() { day += Time.deltaTime / REAL_SECONDS_PER_INGAME_DAY; float dayNormalized = day % 1f; float rotationDegreesPerDay = 360f; clockHourHandTransform.eulerAngles = new Vector3(0, 0, -dayNormalized * rotationDegreesPerDay); float hoursPerDay = 24f; clockMinuteHandTransform.eulerAngles = new Vector3(0, 0, -dayNormalized * rotationDegreesPerDay * hoursPerDay); string hoursString = Mathf.Floor(dayNormalized * hoursPerDay).ToString("00"); float minutesPerHour = 60f; string minutesString = Mathf.Floor(((dayNormalized * hoursPerDay) % 1f) * minutesPerHour).ToString("00"); int currentDay = (int)Mathf.Floor(day); timeText.text = $"{hoursString}:{minutesString}"; dayText.text = $"Day: {currentDay}"; } }
关键修改说明
- 方案1通过保存完整的浮点数时间,解决了仅存整数天数导致的当天进度丢失问题,初始化时加载保存值避免重置
- 方案2利用
DontDestroyOnLoad让时钟对象跨场景保留,无需读写磁盘,适合仅运行时同步的需求 - 移除了冗余变量,简化逻辑,避免重复调用
PlayerPrefs.SetInt的无效操作
内容的提问来源于stack exchange,提问作者MK K
相关产品推荐
相关产品推荐

