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

Unity场景切换后玩家位置保留问题求助及代码排查

Unity返回场景后保留玩家位置的问题修复

问题分析

你的代码存在几个核心问题导致位置无法保留:

  1. 场景加载顺序错误:先设置玩家位置再加载场景,加载主场景后玩家对象会被重新创建,之前设置的位置完全无效。
  2. 缺少位置保存逻辑:代码里只有读取PlayerPrefs的部分,但没有在进入提示场景前保存玩家当前位置的代码。
  3. 跨场景获取玩家对象错误:在提示场景中调用gameManager.GetPlayer()大概率会返回空,因为玩家对象属于主场景,提示场景中不存在该实例。

修复步骤

1. 新增离开主场景时的位置保存逻辑

在主场景的场景切换脚本中,添加进入提示场景前的保存代码:

using UnityEngine;
using UnityEngine.SceneManager;

public class SceneSwitcher : MonoBehaviour
{
    public void GoToHintScene()
    {
        // 保存当前场景名称
        PlayerPrefs.SetString("PreviousScene", SceneManager.GetActiveScene().name);
        
        // 保存玩家当前位置
        GameObject player = GameObject.FindGameObjectWithTag("Player");
        if(player != null)
        {
            PlayerPrefs.SetFloat("PreviousTileX", player.transform.position.x);
            PlayerPrefs.SetFloat("PreviousTileY", player.transform.position.y);
            PlayerPrefs.SetFloat("PreviousTileZ", player.transform.position.z);
            PlayerPrefs.Save(); // 强制写入磁盘,避免数据丢失
        }
        
        SceneManager.LoadScene("HintScene"); // 替换为你的提示场景名称
    }
}

2. 修改返回主场景的逻辑,调整场景加载顺序

修改你的valuestore脚本,改为先加载场景,再在场景加载完成后设置玩家位置:

using UnityEngine;
using UnityEngine.SceneManagement;

public class valuestore : MonoBehaviour
{
    private void Start()
    {
        // 确保该脚本所在对象在场景切换时不被销毁
        DontDestroyOnLoad(gameObject);
    }

    public void GoBack()
    {
        string previousScene = PlayerPrefs.GetString("PreviousScene");
        if (!string.IsNullOrEmpty(previousScene))
        {
            // 注册场景加载完成回调,加载完成后再设置位置
            SceneManager.sceneLoaded += OnSceneLoaded;
            SceneManager.LoadScene(previousScene);
        }
        else
        {
            Debug.Log("未找到上一个场景名称!");
        }
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // 移除回调,避免重复触发
        SceneManager.sceneLoaded -= OnSceneLoaded;
        
        // 读取保存的位置并设置给玩家
        float posX = PlayerPrefs.GetFloat("PreviousTileX");
        float posY = PlayerPrefs.GetFloat("PreviousTileY");
        float posZ = PlayerPrefs.GetFloat("PreviousTileZ");
        
        GameObject player = GameObject.FindGameObjectWithTag("Player");
        if(player != null)
        {
            player.transform.position = new Vector3(posX, posY, posZ);
        }
        else
        {
            Debug.Log("未找到Player对象!请检查标签是否正确");
        }
    }
}

3. 额外注意事项

  • 确保玩家对象的标签确实设置为Player,避免FindGameObjectWithTag找不到目标。
  • 如果需要让玩家不随场景销毁(比如跨场景保留玩家状态),可以给玩家对象添加DontDestroyOnLoad,但要注意在提示场景中临时禁用玩家的显示和交互。
  • 测试时可以通过Edit > Project Settings > Player查看PlayerPrefs的存储路径,确认数据是否正确保存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:22:37