脚本在测试 [x] 次后抛出 NullReferenceException?在 Unity 中

Script throws NullReferenceException after tested [x] amount of times? In Unity

提问人:Issaiah Teneyck 提问时间:5/12/2023 更新时间:5/15/2023 访问量:29

问:

我是第一个承认的人,我的 C# 不流利,但我在学校开始了这个项目,我有 2 个脚本;Game_Handler,Game_Set_Handler。Game_Handler做实际的游戏,而Set_Handler处理我的字典。

这里Game_Set_Handler

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.UI;
using System.Threading.Tasks;
using System.Diagnostics;
using Random = System.Random;


public class Game_Set_Handler : MonoBehaviour
{
    public class Set
    {
        public string? Question { get; set; }
        public int StartingPoints { get; set; }
        public string Answer1 { get; set; }
        public string Answer2 { get; set; }
        public string Answer3 { get; set; }
        public string? Answer4 { get; set; }
        public string? Answer5 { get; set; }

    }

    public Dictionary<int, Set> Sets;

    public void Handler()
    {
        Sets = new Dictionary<int, Set>()
        {
            {1,new Set { Question="sports to play outside", StartingPoints=250, Answer1 = "football", Answer2 = "baseball", Answer3 = "basketball", Answer4 = "soccer", Answer5 = "golf"}},
            {2,new Set { Question="board games", StartingPoints=375, Answer1 = "chess", Answer2 = "checkers", Answer3 = "monopoly",Answer4 = "battleship",Answer5 = "mancala"}},
            {3,new Set { Question="famous religions", StartingPoints=400, Answer1 = "christianity", Answer2 = "islam", Answer3 = "judaism",Answer4 = "buddhism",Answer5 = "hinduism"}},
            {4,new Set { Question="types of bread in the USA", StartingPoints=225, Answer1 = "banana", Answer2 = "sourdough", Answer3 = "white",Answer4 = "wheat",Answer5 = "pumpkin"}},
            {5,new Set { Question="car brands in the USA", StartingPoints=100, Answer1 = "ford", Answer2 = "chevrolet", Answer3 = "toyota",Answer4 = "honda",Answer5 = "volkswagen"}},

        };
    }

    void Start()
    {
        Handler();
    }


    public int Get_Question()
    {
        int value = new Random().Next(0, Sets.Count + 1);
        return value;
    }
}

以下是我如何将两者联系起来(这是Game_Handler):

var dictionary = Parent.GetComponent<Game_Set_Handler>().Sets; //Parent is the Canvas, both scripts are connected to it
int dict_key = Parent.GetComponent<Game_Set_Handler>().Get_Question();

它工作得非常好,直到我测试了 Unity 项目 6 或 7 次,然后每次我之后测试它时都会抛出此错误:

值得注意的是,如果我复制相同的脚本,制作一个新脚本并粘贴它(显然更改了类名),它就可以正常工作,直到我测试它 6 或 7 次。

NullReferenceException: Object reference not set to an instance of an object
Game_Set_Handler.Get_Question () (at Assets/Scripts/Game_Set_Handler.cs:53)
Game_Handler.Start_Game () (at Assets/Scripts/Game_Handler.cs:60)
Game_Handler.Start () (at Assets/Scripts/Game_Handler.cs:121)

在过去的 2 天里,我一直坚持下去,我即将接受 L 并继续前进,如果有人能提供帮助,我将不胜感激。

我尝试用不同的函数替换该函数,但错误仍然存在,我已经复制了它 3 次,只是为了测试目的,但我觉得当我将其导出到可执行文件中时,它也会发生。

C# unity-game-engine nullreferenceException 对象引用

评论

1赞 Jon Skeet 5/12/2023
您还没有向我们展示您如何使用 的结果,但是当您只有五个问题时,您为什么希望它给出六个不同值 (0-5) 之一?Get_Question
0赞 Issaiah Teneyck 5/12/2023
我做了 +1,因为它一开始不会给我第 5 组,但现在不在那里,这就是我使用 Get_Question() 的方式dict_key = Parent.GetComponent<Game_Set_Handler>().Get_Question(); question = dictionary[dict_key].Question;
0赞 Jon Skeet 5/12/2023
如果返回 0,您预计会发生什么?(听起来你根本不需要字典......如果您只是按索引访问元素,只需使用列表...Random.Next()
0赞 Issaiah Teneyck 5/12/2023
好吧,我完全基于我对 Lua 和 Python 的了解来制作这个,我以前用这些语言和词典制作过同样的游戏是有道理的,但我仍然很难理解这里的词典。我最初的想法是拥有类似的东西,这是我想出的最好的东西。关键是我可以循环访问,得到一个随机问题,以及与该问题相关的统计数据{ ["question used to reference"] = {Answer_Points, {"list of answers"}}
0赞 Ceres 5/12/2023
如果在 Handler() (或 Start()) 之前调用 Get_Question() 集为 null 并且您无法访问 Count off a null 值,则可能会发生这种情况。您可以解决该问题或检查 Sets 在 Get_Question 中是否为 null,然后从那里进行处理。

答:

0赞 Zen Of Kursat 5/12/2023 #1
    int value = new Random().Next(0, Sets.Count);//remove +1 may fix your problem

请尝试此方法:

public int Get_Question()
{
    if (Sets == null)
    {
       Handler();
        //Debug.LogError("Sets dictionary is null!");
        //return -1;
        
        
    }

    int value = new Random().Next(0, Sets.Count);
    return value;
}

此外,将以下代码块移动到文件顶部:

void Start()
{
    Handler();
}
0赞 Issaiah Teneyck 5/15/2023 #2

好吧,所以我真的不知道为什么这会修复它,也许它会再次崩溃,但这毫无意义。我部分使用了上面的答案,但它不起作用,然后我意识到没有任何问题,这是我Game_Handler,无论出于何种原因,我的公共词典都无法访问,所以我在错误上方添加了一个打印语句,错误消失了。Game_Set_Handler

旧代码(片段):

    void Start_Game()
    {
        if (timerOn == false){
            timerOn = true;
        }
        if (gamePlaying == false){
            gamePlaying = true;
        }
        var dictionary = Parent.GetComponent<Game_Set_Handler>().Sets; // NullRefError at this line
        string question = dictionary[dict_key].Question;

当前有效的代码:

    void Start_Game()
    {
        if (timerOn == false){
            timerOn = true;
        }
        if (gamePlaying == false){
            gamePlaying = true;
        }
        print(Parent.GetComponent<Game_Set_Handler>().Get_Question());
        var dictionary = Parent.GetComponent<Game_Set_Handler>().Sets; // No error at all now
        string question = dictionary[dict_key].Question;

如果有人对为什么会这样有解释,我很想听听,但它对我来说没有多大意义(Get_Question在使用其索引之前被调用,这是我唯一的解释,所以它不起作用)