简体   繁体   English

重新启动游戏后,GameObjects将不会加载

[英]GameObjects will not load after game Restarts

I am making a maze game and the keys which are needed to be collected to complete it wont appear again if the game restarts, I get the following error; 我正在制作一个迷宫游戏,如果重新启动游戏,则需要再次收集才能完成的迷宫键,但出现以下错误;

MissingReferenceException: The object of type 'MazeDirectives' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.

I am just disabling the MazeKey object, not destroying it, can anyone help? 我只是禁用MazeKey对象,而不是销毁它,有人可以帮忙吗? Below is my code; 下面是我的代码;

MazeKey.cs MazeKey.cs

using UnityEngine;
using System.Collections;

public class MazeKey : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {

        transform.parent.SendMessage("OnKeyFound", SendMessageOptions.DontRequireReceiver);
        gameObject.SetActive(false);
    }
}

MazeDirectives.cs MazeDirectives.cs

MazeGoal mazeGoal;
MazeKey mazeKey;

void StartDirectives()
    {
        mazeGoal = Instantiate(mazeGoalPrefab, MazeGenerator.instance.mazeGoalPosition, Quaternion.identity) as MazeGoal;
        mazeGoal.transform.SetParent(transform);

        mazeKeyPositions = MazeGenerator.instance.GetRandomFloorPositions(keysToFind);

        for (int i = 0; i < mazeKeyPositions.Count; i++)
        {
            MazeKey mazeKey = Instantiate(mazeKeyPrefab, mazeKeyPositions[i], Quaternion.identity) as MazeKey;
            mazeKey.transform.SetParent(transform);

        }
    }

To restart the game I use the code below; 要重新启动游戏,请使用以下代码;

void OnTriggerEnter2D(Collider2D other)
{
    if (other.tag == "Player")
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        gameObject.SetActive(true);
    }
}

MazeGoal.cs MazeGoal.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MazeGoal : MonoBehaviour
{

public Sprite closedGoalSprite;
public Sprite openedGoalSprite;

void Start()
{

    GetComponentInChildren<SpriteRenderer>().sprite = closedGoalSprite;



}

public void OpenGoal()
{
    GetComponentInChildren<SpriteRenderer>().sprite = openedGoalSprite;
}

void OnTriggerEnter2D()
{
    transform.parent.SendMessage("OnGoalReached", SendMessageOptions.DontRequireReceiver);
}

Explenation 讲解

The exception you get is not talking about the MazeKey object but rather the MazeDirectives component. 您得到的例外不是谈论MazeKey对象,而是MazeDirectives组件。

Unfortunately you hit the most important information in the comments: 不幸的是,您在评论中遇到了最重要的信息:

private void Awake() 
{ 
    MazeGenerator.OnMazeReady += StartDirectives; 
}

so OnMazeReady seems to be static and not instanced so it will not be destroyed when a new Scene is loaded but keeps intact bloating into the new Scene! 因此OnMazeReady似乎是static而不是实例化的,因此在加载新场景时不会被破坏,但会保持原样膨胀到新场景中!

When you call 你打电话时

MazeGenerator.OnMazeReady += StartDirectives;

you add the call to the StartDirectives method of an instance of MazeDirectives as listener to that static event. 您可以将调用添加到StartDirectives实例的MazeDirectives作为该static事件的侦听器。

Now when you reload the Scene all GameObject s and thereby their instances of components are destroyed 现在,当您重新加载Scene时,所有GameObject都因此销毁了它们的组件实例

=> so is the instance of MazeGenerator ... BUT the static event OnMazeReady is not destroyed! => MazeGenerator的实例也是MazeGenerator ... 但是 static事件OnMazeReady 没有被销毁!

so after the next Awake call you now have two listeners 所以在下一个Awake通话之后,您现在有两个听众

  • The one from the "second"/new loaded Scene 来自“第二” /新加载场景的一个
  • Still the "old" one you added the first time 还是您第一次添加的“旧”文件

But since the instance of MazeDirectives you added the first listener for is destroyed when the scene is reload and a new instance generated, you get that exception 但是由于MazeDirectives添加场景并生成新实例时,您添加的第一个侦听器的MazeDirectives实例被销毁,因此您将获得该异常

MissingReferenceException: The object of type 'MazeDirectives' has been destroyed but you are still trying to access it. MissingReferenceException:'MazeDirectives'类型的对象已被破坏,但您仍在尝试访问它。 Your script should either check if it is null or you should not destroy the object. 您的脚本应检查其是否为null或不破坏该对象。

when the method tries to access the transform value of the destroyed instance. 当该方法尝试访问被销毁实例的transform值时。


Solution 1a 解决方案1a

So you should remove the listener when you destroy the instance 因此,在销毁实例时应删除侦听器

private void OnDestroy()
{
     MazeGenerator.OnMazeReady -= StartDirectives;
}

Solution 1b 解决方案1b

or overwrite it with only exactly one listener at a time 或一次只用一个监听器覆盖它

private void Awake() 
{ 
    MazeGenerator.OnMazeReady = StartDirectives; 
}

this second aproach obviously is only useful when there is no other instance or class listening to that event. 第二种方法显然仅在没有其他实例或类在监听该事件时才有用。 The question is how much sense does it make to use an event than? 问题是,使用事件比这有意义多少? And I would than anyway remove it if not needed just to be sure 而且我还是会确保不需要时将其删除

private void OnDestroy()
{
     MazeGenerator.OnMazeReady = null;
}

Solution 2 解决方案2

I would prefere this solution. 我更喜欢这种解决方案。

Don't make MazeGenerator.OnMazeReady static at all. 完全不要将MazeGenerator.OnMazeReady静态。 Since anyway I see that you are using a Singleton pattern eg in 因为无论如何,我看到您正在使用Singleton模式,例如

 MazeGenerator.instance.mazeGoalPosition

you could instead just make OnMazeReady Non-static and instead use it the same way: 您可以改为使OnMazeReady为非静态,并以相同的方式使用它:

private void Awake()
{
    MazeGenerator.instance.OnMazeReady += startDirectives;
}

so it will be destroyed together with that instance of MazeGenerator . 因此它将与MazeGenerator实例一起被销毁。


General note 一般说明

I would always remove all listeners I ever added as soon as possible to avoid exactly the issue you have. 总是会尽快删除我曾经添加的所有侦听器,以避免出现确切的问题。

You could additionally remove it eg already inside of StartDirectives to make sure the method is executed only once even if the same Scene "accidentely" invoked OnMazeReady twice. 您可以另外删除它,例如已经在StartDirectives内部将其删除,以确保即使同一场景“偶然”两次调用OnMazeReady该方法也仅执行一次。

Hint: I said additionally since it is always save/possible to remove a listener even if it wasn't added before and you should allways leave the one in OnDestroy in case the StartDirectives is never called before the object is destroyed. 提示:我说因为它总是保存/可去除即使之前未添加监听器,你应该离开百达一中OnDestroy万一StartDirectives对象被销毁之前不会被调用。

Update: 更新:

This answer is wrong at first place. 首先,这个答案是错误的。 The exception is complaining about accessing the MazeDirectives 's transform , not mazeGoal object. 例外是抱怨访问MazeDirectivestransform而不是mazeGoal对象。 But the comments below did give some useful info. 但是下面的评论确实提供了一些有用的信息。 So I'm keeping this post for references. 因此,我保留此帖子以供参考。

For complete solution, see here . 有关完整的解决方案,请参见此处


From the line mazeGoal.transform.SetParent(transform); mazeGoal.transform.SetParent(transform);mazeGoal.transform.SetParent(transform); throws the exception: 引发异常:

MissingReferenceException: The object of type 'MazeDirectives' has been 
destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.

From here : 这里

The load of a new Scene destroys all current Scene objects. 新场景的负载会破坏所有当前的场景对象。

The mazeGoal has been destroyed when you called the mazeGoal已经被毁坏了,当你调用

SceneManager.LoadScene(SceneManager.GetActiveScene().name);

to restart the game. 重新启动游戏。

And from MonoBehaviour.Awake() , MonoBehaviour.Awake()中

Awake is called only once during the lifetime of the script instance. 在脚本实例的生存期内,仅一次调用Awake。

Since you only assign the mazeGoal variable inside StartDirectives function which been called in Awake , after loading the same scene again, the actual object of mazeGoal has been destroyed. 由于仅在Awake调用的StartDirectives函数内分配了mazeGoal变量,因此在再次加载同一场景后, mazeGoal的实际对象已被破坏。

If you want to reuse the same object when loading a new scene, you can use DontDestroyOnLoad to keep the mazeGoal object. 如果要在加载新场景时重用同一对象,则可以使用DontDestroyOnLoad保留mazeGoal对象。

Or you can move the StartDirectives to Start function which will be called every time the gameobject is created and reinitialize your mazeGoal . 或者,您可以将StartDirectives移至Start函数,该函数将在每次创建游戏对象时调用,并重新初始化mazeGoal

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM