当前位置: 首页 > 知识库问答 >
问题:

Unity:使用GameManager添加“持久场景”后出现奇怪的场景过渡错误

倪阳飇
2023-03-14

我做了一个很基本的2D游戏来学习。我有两个场景,在它们之间切换效果很好。我使用空的游戏对象作为场景的开始/退出点,这样游戏就知道在通过点X退出后将玩家放在点X上(例如,如果我走出门,就从屋外退出)。

然后,我添加了一个“Scene0”,用于持久的通用脚本,如GameManager、Sounds、Music等,其中只有一个名为“Controller”的对象,我不使用destroyoonload()。添加此场景后,然后立即切换到主场景,突然游戏开始表现得非常奇怪;

当我第一次从主场景(Scene1)移动到第二场景(Scene2)时,效果很好,但当我离开场景2回到场景1时,玩家就在一个不知名的地方诞生了。只有当我从持久场景启动游戏时,才会发生这种情况。

我不知道出了什么问题,我没有添加任何干扰场景过渡的内容,到目前为止,我添加的只是用于测试的playerHealth。

附加到my(persistent)Controller的脚本:

DDOL:

public class DDOL : MonoBehaviour {

    // Use this for initialization
    void Awake () {
        DontDestroyOnLoad (gameObject);
    }

}

游戏管理器:

public class GameManager : MonoBehaviour {

    public static GameManager manager;

    public int playerMaxHealth;
    public int playerCurrentHealth;

    void Awake(){
        if (manager == null) {
            manager = this;
        } else if (manager != this) {
            Destroy (gameObject);
        }
    }

    // Use this for initialization
    void Start () {
        SceneManager.LoadScene("test_scene");
    }

    // Update is called once per frame
    void Update () {

    }
}

附加到我的StartPoint的脚本:

玩家起点:

public class PlayerStartPoint : MonoBehaviour {

    private PlayerController thePlayer;
    private CameraController theCamera;

    public Vector2 startDir;

    public string pointName;

    // Use this for initialization
    void Start () {
        thePlayer = FindObjectOfType<PlayerController> ();

        if (thePlayer.startPoint == pointName) {
            thePlayer.transform.position = transform.position;
            thePlayer.lastMove = startDir;

            theCamera = FindObjectOfType<CameraController> ();
            theCamera.transform.position = new Vector3(transform.position.x, transform.position.y, theCamera.transform.position.z);
        }
    }
}

最后退出点:

加载新区域:

public class LoadNewArea : MonoBehaviour {

    public string levelToLoad;
    public string exitPoint;
    private PlayerController thePlayer;

    // Use this for initialization
    void Start () {
        thePlayer = FindObjectOfType<PlayerController> ();
    }

    void OnTriggerEnter2D(Collider2D other){
        if (other.gameObject.name == "Player") 
        {
            SceneManager.LoadScene(levelToLoad);
            thePlayer.startPoint = exitPoint;
        }
    }
}

编辑:在将我的所有DDOL游戏对象移动到场景前,它成功了。因此,我可以假设故障发生在播放器或相机的函数内部,因为当它们在场景1中启动时,每次我进入场景时都会调用它们(仅DDOL)。我试着调整它们的Start()函数,如下所示:

原装相机:

void Start () {
        Debug.Log("Starting camera");
        if (!cameraExists) {
            cameraExists = true;
            DontDestroyOnLoad (gameObject);}
           else{
        Destroy (gameObject);
        }
    }

更换相机:

void Start () {
            DontDestroyOnLoad (gameObject);
        }

同样的变化也发生在球员身上。显然,这不起作用,因为每次我进入场景1时,它都会创建一个新的摄影机/播放器(顺便问一下,为什么在我进入场景2时它不尝试创建它们?是因为它们从场景1开始吗?)。然而,新的播放器/摄像机确实从正确的位置开始,如果我缩小,我可以看到旧的播放器/摄像机像以前一样处于错误的位置。所以当第二次调用他们的Start()时,似乎会发生一些奇怪的事情。


共有3个答案

夏嘉德
2023-03-14

玩家在两个场景之间是否持久(他是否有DontDestroyOnLoad)?如果没有,那么这可能就是原因-您可以尝试使用加法模式加载场景,或者在正确的位置实例化场景加载中的播放器。

白通
2023-03-14

使用调试器。在相关位置设置断点,例如PlayerStartPoint。Start()LoadNewArea。OnTriggerSet2D()并检查它们是否已执行

  • 在适当的时候
  • 正确的次数
  • 与期望值

这会让你看到事情失控的地方。

如果您使用Visual Studio,请安装https://marketplace.visualstudio.com/items?itemName=SebastienLebreton.VisualStudio2015ToolsforUnity以便能够从Visual Studio中调试Unity。如果您不使用Visual Studio,您可能应该这样做。

唐高朗
2023-03-14

您已经提到您有这样的代码,

void Start () {
        Debug.Log("Starting camera");
        if (!cameraExists) {
            cameraExists = true;
            DontDestroyOnLoad (gameObject);}
           else{
        Destroy (gameObject);
        }
    }

请注意,不幸的是,这只是“完全不正确”,呵呵:)

您在问题中提到的问题(预加载场景等)与此处的问题完全无关。

在Unity中,如果在加载场景a、b、C时,角色C在场景a、b、C之间持续存在,则必须在其自己的(可能是空的)场景中启动C,为了方便起见,不能使用“a”启动C。

模式是,在a、b、c中的每一个都有一行代码,比如p=FindObjectOfType

现在,关于你所看到的不寻常行为的具体谜题。

我明白你想知道为什么你在观察你所做的事情。

这是对以下问题的混淆的结合:1-唤醒和开始之间的区别,2-对脚本执行顺序的混淆{但请参阅下面1} 3-对Destroy和Destroy的混淆立即4-不使用调试。日志足够,并且没有在其中使用gameObject.name(在Unity中,对哪个对象在Debug中说话感到非常困惑是很常见的。日志)5-当你提到你看到另一个对象“在一边”,在这种情况下很容易完全混淆哪一个是哪一个6-混淆计算机编程概念的“实例化”(即类或对象)和“实例化”(令人困惑的是,这是同一个词——完全不相关)游戏对象。

如果你胡乱处理所有这些问题,你会发现你所看到的行为的解释!

但这并不算什么;在“C..a b C”示例中的Unity中,您必须事先单独创建C。

撇开它不谈,千万不要为了解决问题而在统一中摆弄脚本执行顺序html" target="_blank">系统;它只用于R

 类似资料:
  • 我在云上保存了一个持久的锚(365天)。现在,我想找回它。我可以很好地使用谷歌在其示例项目之一中提供的代码。然而,我想使用场景形式,因为我想在之后做一些操作(绘制3D形状),这在场景形式中更容易做到。然而,我似乎无法解决持续的云锚。我在网上找到的所有例子,都不处理持久的云锚,它们只处理正常的24小时云锚。 我写的上面的更新函数有什么错误吗?CloudAnchorManager类与Google在其持

  • 接口说明 如果用户想对比两个场景中的数据(如历史数据对比、规划前后的数据对比等)来统计一些信息,Wish3DEarth团队新增了双屏对比的接口,开发者可以通过该接口,来建立主屏与副屏之间的关联性。 如需调用,请访问 开发者文档 来查看详细的接口使用说明 该接口仅开放给已获取SDK的开发者 API地址 POST /api/contrasts/1.0.0/add 是否需要登录 是 请求字段说明 参数

  • 问题内容: 在Objective-C中,使用Sprite-Kit,我将在Objective-C中 成功 使用类似以下代码的内容来展示新场景 在尝试将我的简单游戏移植到Swift时,到目前为止,我已经完成了这项工作… 但是我不知道要写什么代码才能真正过渡到另一个场景。问题: 有人可以提供在Swift中使用SKTransition的示例吗? 假设您将使用Objective-C,通常是否会创建另一个“文

  • WebAssembly 的整体目标 定义了 WebAssembly 适合做什么。哪些是在 Web 平台可以实现的,哪些是非 Web 平台可以实现的。下面给出了一个不完善的无序列表,包括应用/领域/计算等方向,它们可能将从 WebAssembly 中受益的, WebAssamlby 的设计过程中也会将它们做为用例。 在浏览器中 更好的让一些语言和工具可以编译到 Web 平台运行。 图片/视频编辑。

  • 4.1 使用场景 Camel管理端内部定义了很多模型对象。接口接受的数据均是模型对象对应的json。 Camel管理端,提供了界面和接口两种方式。这两种方式均可对Server、Upstream等配置信息进行更改,以及发布配置文件。那么什么场景下应该使用接口呢? 通过界面对配置文件进行更改,是一种可视化操作,非常的直观。界面方式适用于编辑配置信息,如增加location等操作。 如果通过界面进行配置

  • 学件 “学件”(Learnware)一词由南京大学周志华老师原创,学件(Learnware) = 模型(model) + 规约(specification),具有可重用、可演进、可了解的特性。 很多人可能在自己的应用中已经建立了类似的模型,他们也很愿意找到一个地方把这些模型分享出去。这样一来,一个新用户想要应用,也许不用自己去建立一个,而是先到“学件”市场上找一找有没有合适的,拿来直接或修改后使用