You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:17:50