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

Unity关卡选择场景中如何保存关卡最佳通关时长?

解决方案步骤

一、最佳时长的存储与更新逻辑

用PlayerPrefs存储每个关卡的最佳时长,它适合存储简单键值对数据,无需复杂序列化。通关时对比当前耗时与存储的最佳时长,首次通关直接保存,耗时更短时覆盖原数据。

// 在关卡通关逻辑中调用此方法
public void UpdateBestTime(int levelIndex, float currentTime)
{
    string key = $"BestTime_Level{levelIndex}";
    if (PlayerPrefs.HasKey(key))
    {
        float bestTime = PlayerPrefs.GetFloat(key);
        if (currentTime < bestTime)
        {
            PlayerPrefs.SetFloat(key, currentTime);
            PlayerPrefs.Save(); // 立即保存避免数据丢失
        }
    }
    else
    {
        PlayerPrefs.SetFloat(key, currentTime);
        PlayerPrefs.Save();
    }
}

二、关卡选择场景展示最佳时长

在关卡选择场景的UI文本组件中,加载对应关卡的最佳时长,无通关记录时显示提示文本。

// 关卡选择场景的UI脚本
public class LevelSelectUI : MonoBehaviour
{
    public Text[] levelTimeTexts; // 每个关卡对应的显示文本

    void Start()
    {
        LoadAllBestTimes();
    }

    void LoadAllBestTimes()
    {
        for (int i = 0; i < levelTimeTexts.Length; i++)
        {
            int levelIndex = i + 1; // 假设关卡从1开始编号
            string key = $"BestTime_Level{levelIndex}";
            if (PlayerPrefs.HasKey(key))
            {
                float bestTime = PlayerPrefs.GetFloat(key);
                // 格式化时间为分:秒.毫秒格式
                string timeStr = string.Format("{0:00}:{1:00}.{2:00}", 
                    Mathf.Floor(bestTime / 60), 
                    Mathf.Floor(bestTime % 60), 
                    Mathf.Floor((bestTime * 100) % 100));
                levelTimeTexts[i].text = $"最佳时长: {timeStr}";
            }
            else
            {
                levelTimeTexts[i].text = "未通关";
            }
        }
    }
}

三、解决关卡选择场景计时器重置问题

问题根源是计时器脚本在非游戏关卡场景也启动了计时,以下两种方案可解决:

方案1:场景名称判断

通过当前场景名称识别是否为游戏关卡,仅在关卡场景开启计时:

public class LevelTimer : MonoBehaviour
{
    private float currentTime;
    private bool isTiming;

    void Start()
    {
        // 假设游戏关卡场景名称包含"Level",如"Level1"、"Level2"
        if (SceneManager.GetActiveScene().name.Contains("Level"))
        {
            isTiming = true;
            currentTime = 0;
        }
        else
        {
            isTiming = false;
        }
    }

    void Update()
    {
        if (isTiming)
        {
            currentTime += Time.deltaTime;
        }
    }

    // 通关时调用,传入当前关卡索引
    public void OnLevelComplete(int levelIndex)
    {
        isTiming = false;
        UpdateBestTime(levelIndex, currentTime);
    }
}

方案2:全局状态控制

用静态类管理游戏状态,精准控制计时开关:

// 全局静态类,管理游戏状态
public static class GameState
{
    public static bool IsInGameLevel { get; set; }
}

// 关卡加载脚本
public class LevelLoader : MonoBehaviour
{
    public void LoadLevel(int levelIndex)
    {
        GameState.IsInGameLevel = true;
        SceneManager.LoadScene($"Level{levelIndex}");
    }

    public void LoadLevelSelect()
    {
        GameState.IsInGameLevel = false;
        SceneManager.LoadScene("LevelSelect");
    }
}

// 计时器脚本
public class LevelTimer : MonoBehaviour
{
    private float currentTime;

    void Update()
    {
        if (GameState.IsInGameLevel)
        {
            currentTime += Time.deltaTime;
        }
    }

    public void OnLevelComplete(int levelIndex)
    {
        GameState.IsInGameLevel = false;
        UpdateBestTime(levelIndex, currentTime);
    }
}

额外注意事项

  • 测试时可调用PlayerPrefs.DeleteAll()清空测试数据;
  • 若需多用户存档,可改用JsonUtility序列化到本地文件,单用户场景下PlayerPrefs足够;
  • 计时器脚本若需跨场景保留,可添加DontDestroyOnLoad并实现单例模式避免重复实例化。

内容的提问来源于stack exchange,提问作者AvaloN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:25:19