公共静态 Dictionary<String,GameObject> 中的游戏对象在 Unity 中的场景更改时被销毁

Posted

技术标签:

【中文标题】公共静态 Dictionary<String,GameObject> 中的游戏对象在 Unity 中的场景更改时被销毁【英文标题】:GameObjects in a public static Dictionary<String,GameObject> are destroyed on scene changes in Unity 【发布时间】:2017-06-23 12:23:53 【问题描述】:

第一次正式声明: 编程语言:Unity 中的 C#(MonoBehavior) 我的技能水平:有点菜鸟(不到半年的 c# 经验)。

我正在制作一个方块破坏游戏(Arkanoid)并且正在制作一个成就系统。游戏是一次性的,当您关闭网络构建时,所有内容都会被删除(没有缓存,没有文件保存,没有可序列化的类)。

成就系统包含: “成就”类:很多变量和一些跟踪进度的方法。它附加到具有相同名称的空游戏对象的脚本。普通班。

“AManager”类。初始化“成就”类的一堆副本的类,给它们单独的值并将它们添加到下面提到的字典中。辛格尔顿班。

“AcheivementDictionary”类:只包含私有静态字典和访问方法。也是单例类

问题:

成就是在第一个场景的“开始”时制作和添加的。添加它们后,我检索游戏对象并测试它们的标签是否有效,一切都很好。然后从我的“levelManager”类中,我从下一个场景调用相同的方法,并收到一条消息,即游戏对象已被销毁。如果我测试它们,它们也会返回 null。

所以...我真正的问题是:

如何使我的成就游戏对象的实例化副本在 Unity 中的所有场景更改中持续存在?

代码参考:

我不认为“成就”是有任何问题的类,如果您需要该类的代码,只需大声疾呼。

“经理”

public class Amanager : MonoBehaviour 

    public static Amanager acheivementManager = null;
public GameObject myAchObject;

void Awake () 
        if (acheivementManager != null)  
        Destroy(gameObject);
         else 
            acheivementManager = this;
            GameObject.DontDestroyOnLoad(gameObject);
        
    

void Start () 

    myAchObject.AddComponent<Acheivement>();


    initAcheivements ("completeLevelThree", "Level 3", "Complete level 3","Level", 3,5);
    initAcheivements ("completeLevelOne", "Level 1", "Complete level 1","Level", 1,5);
    

private void initAcheivements(string inAch, string inNavn, string inHow, string inCountType, int goalVal, int Reward) 


            Vector3 loc = new Vector3 (0f, 0f,0f);
            GameObject testAch;
            testAch = Instantiate(myAchObject, loc, Quaternion.identity) as GameObject; 
            //testLives.SetActive (true);
            //testLives.gameObject.tag = "clone";

        testAch.GetComponent<Acheivement>().setName(inNavn);
        testAch.GetComponent<Acheivement>().setHowToGet(inHow);
        testAch.GetComponent<Acheivement>().setCountType(inCountType);
        testAch.GetComponent<Acheivement>().setGoalVal(goalVal);
        testAch.GetComponent<Acheivement>().setReward(Reward);
        testAch.tag = inCountType;
        Debug.Log ("InitiAch did run");
        AcheivementDictionary._Instance.achRegAdder(inNavn,testAch);

成就词典代码:

public class AcheivementDictionary : MonoBehaviour 
public static AcheivementDictionary _Instance;

    private static Dictionary<string,GameObject> AchReg = new Dictionary<string,GameObject>();

void Awake () 
        if (_Instance != null)  
            Destroy(gameObject);
         else 
            _Instance = this;
            GameObject.DontDestroyOnLoad(gameObject);
    
    

    public void achRegAdder (string inName, GameObject theAch) 
    AchReg.Add(inName,theAch);
    Debug.Log ("achRegAdded did run");
    readThisString = inName;
    tryRead = true;
    

    private void readIt() 
    Debug.Log ("readItRan"); 
    GameObject testShit; 
    AchReg.TryGetValue("Level 1",out testShit);
    Debug.Log("if it works level should stand there ---> " + testShit.tag);
    tryRead = false;
    

    public void achRegReader () 
        readIt ();
    

运行时,控制台中会出现以下消息:

initAch 确实运行了

achRegAdded 确实运行了

initAch 确实运行了

achRegAdded 确实运行了

readItRan

如果它工作水平应该站在那里 ---> 水平

readitRan

MissingReferenceException:“GameObject”类型的对象已被销毁,但您仍在尝试访问它。您的脚本应该检查它是否为空,或者您不应该销毁对象。

(这个错误是在尝试访问存储对象的标签时出现的,并发生在以下方法调用中:Debug.Log("如果它工作级别应该站在那里 ---> " + testShit.tag);)

这是用于在 achRegReader 失败时调用的代码行(来自另一个类): AcheivementDictionary._Instance.achRegReader();

另外:如果我计算字典中对象的数量,它确实返回 2。它们只是被破坏了,我真的不明白为什么。我的程序中没有任何代码可以破坏这些。

我的猜测是这样的:

关于在 Singelton 类中放置静态字典有一些我不明白的问题。 Acheivements 的实例化副本不会在场景中持续存在,因为它们不是 dontDestroyOnLoad,即使处理它们的两个类都是。 无论哪种方式,在过去的 6 个小时的斗争中,我都没有设法隔离或解决问题,请帮助!

【问题讨论】:

忘了提一下:我在所有场景变化上都调用了“读取”消息。我在进行初始化的开始菜单中没有收到任何错误消息,但之后在所有场景加载时我都会收到相同的错误消息。 我的猜测是场景变化之类的东西会破坏游戏对象。尝试在initAcheivements 中添加testAch.transform.parent = transform; 成功了,我爱你!另外...为什么它起作用了?我怎么给你解决它的功劳,我没有看到“他解决了这个问题”按钮:D 您的问题是实例化的对象从未被告知 DontDestroyOnLoad,只有实例化它们的对象。您要么必须在实例化对象上调用 DontDestroyOnLoad,要么使它们成为您使用 DontDestroyOnLoad 的初始对象的子对象,如 Bijan 建议的那样。 太好了,谢谢 :) 我在遗产方面还有很多东西要学!我确实尝试过(非常努力地)对实例化对象进行 dontDestroyOnLoad,但他们不会听到它。即使它们只在上面一行被制作成 GameObjects,他们仍然说我不能在 Objects 上使用“DontDestroyOnLoad”,并且我不能显式或隐式地将我的“Object”转换为“GameObject”(甚至认为它是一个 GameObject 开头)。 【参考方案1】:

在 initAcheivements 函数中,要么

testAch.transform.setParent(transform);

DontDestroyOnLoad(testAch);

您的问题是由于 testAch 不是不会被销毁的对象的子对象,或者 testAch 不是不会被销毁的对象本身。

针对您的评论,我迅速编写了这段代码,它没有给我任何问题,我可能遗漏了什么吗?

Vector3 loc = new Vector3(0f, 0f, 0f);
var testAch = Instantiate(myAchObject, loc, Quaternion.identity) as GameObject;
DontDestroyOnLoad(testAch);

【讨论】:

以上是关于公共静态 Dictionary<String,GameObject> 中的游戏对象在 Unity 中的场景更改时被销毁的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Dictionary<string, string> 变量从后面的代码传递到 asp.net?

将 [Dictionary<String,Any?>] 转换为 [Dictionary<String,Any!>] ?迅速 3

如何在 C# 中将 Dictionary<string, object> 转换为 Dictionary<string, string>

如何将 List<Dictionary<string, byte[]> 对象添加到 Dictionary<string, byte[]> [重复]

检查 List<Dictionary<string,object>> 中是不是存在 Dictionary<string,object>? [关闭]

Dictionary 嵌套Dictionary