Unity“ GameObject”类型的对象已被破坏

时间:2019-10-25 18:19:58

标签: c# unity3d

我的选项菜单中有2个按钮,“返回主菜单”和“静音” 这些按钮中的每个按钮都附有脚本,并在按下脚本时调用脚本的OnPress()方法。 我还有一个主要的Level对象/脚本,可以处理所有场景加载和填充。 因此,主菜单按钮的脚本在其Start中执行FindObjectOfType(),然后在其OnPress()中调用level.LoadStartScene()。 静音按钮的脚本执行相同的操作,但调用level.ToggleMuteMusic()。 因此,此操作之前非常完美,但是随后我使用以下代码将关卡设置为单例:

public void Awake() {
    InitializeSingleton();
}

private void InitializeSingleton() {
    if (FindObjectsOfType(GetType()).Length > 1) {
        Destroy(gameObject);
    } else {
        DontDestroyOnLoad(gameObject);
    }
}

因此,现在主菜单按钮可以正常工作,但是静音按钮会出现错误;我认为这是因为在Start()中它找到了一个旧的对象,然后一个带有DontDestroyOnLoad的对象进入并删除了旧的对象,但是为什么主菜单按钮可以工作?

静音按钮代码:

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

public class MuteButton : MonoBehaviour {

[SerializeField] string mutedText = "Unmute Music";
[SerializeField] string unmutedText = "Mute Music";

private Level level;
private TextMeshProUGUI myText;

public void Start() {
    level = FindObjectOfType<Level>();
    myText = GetComponent<TextMeshProUGUI>();
}

public void OnPress() {
    if (level == null) {
        Debug.Log("log 1");
    }
    level.ToggleMuteMusic();
    bool muteMusic = level.GetMuteMusic();
    if (muteMusic == true) {
        myText.SetText(mutedText);
    } else if (muteMusic == false) {
        myText.SetText(unmutedText);
    }
}

}

菜单按钮代码:

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

public class MenuButton : MonoBehaviour {

Level level;

public void Start() {
    level = FindObjectOfType<Level>();
}

public void OnPress() {
    level.LoadStartScene();
}
}

完全错误:

MissingReferenceException:'GameObject'类型的对象已被破坏,但您仍在尝试访问它。 您的脚本应检查其是否为null或不破坏该对象。 UnityEngine.GameObject.GetComponent [T]()(在C:/buildslave/unity/build/Runtime/Export/Scripting/GameObject.bindings.cs:28) Level.ToggleMuteMusic()(位于Assets / Scripts / Level.cs:74) MuteButton.OnPress()(在Assets / Scripts / MuteButton.cs:23)

感谢您的时间:)

1 个答案:

答案 0 :(得分:0)

确定执行该问题的确切顺序可能有点困难,但是您丢失了Start()中由Awake()处理的引用这一事实很奇怪。过去,我在Start()中使用FindObjectOfType<>时遇到了问题,所以也许最好改变一下处理单例的方式。

我建议您使您的等级 static变得更容易,因为您已经在实现Singleton形式。

下面是一个如何重写Level.cs文件顶部的示例:

public static Level instance;

private void Awake()
{
    if (instance != null && instance != this)
    {
        Destroy(this.gameObject);
        return;
    }
    else
    {
        instance = this;
    }
    DontDestroyOnLoad(this.gameObject);
}

这将导致它一次创建一个Level类,然后销毁它的所有后续版本(例如,当您重新加载放置它的场景时)。

现在,要在其他脚本中引用它,则无需再次使用FindObjectOfType<Level>()!您可以像这样静态引用Level.instance

//New way to call ToggleMuteMusic()
Level.instance.ToggleMuteMusic();

希望这会有所帮助!