即使我使用变量获得null错误

问题描述:

我想学习MonoGame,我正在尝试做基本的东西,我已经想到了我自己的大部分,但我得到一个空指针,我不知道为什么。我试图让MainMenuScene只绘制纹理,但在SceneManager中currentScene不断给我空指针,我不知道为什么。我张贴我的SceneManager代码,但其余的将在github上。它没有太多的代码,所以它不应该花很长时间,如果你看看它。我感到非常困惑,我不知道该怎么去谷歌试图弄清楚自己。即使我使用变量获得null错误

https://github.com/eatmykhack/MonoGame.git

using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.Graphics; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Tutorial.Scenes; 

class SceneManager 
{ 
    private static SceneManager instance = new SceneManager(); 
    Scene currentScene, newScene; 

    Dictionary<string, Scene> sceneDirectory =new Dictionary<string, Scene>(); 

    public static SceneManager getInstance() 
    { 
     return instance; 
    } 

    public static Scene getCurrentScene() 
    { 
     return instance.currentScene; 
    } 

    public static void changeScene(Scene scene) 
    { 

    } 

    public static void addScene(string sceneName) 
    { 
     instance.newScene = instance.sceneDirectory[sceneName]; 
    } 

    public void update() { currentScene.Update(); } 
    public void draw(SpriteBatch spriteBatch) { currentScene.Draw(spriteBatch); } 

    public void Initialize() 
    { 
     instance.sceneDirectory["MainMenuScene"] = new MainMenuScene(); 

     instance.currentScene = instance.sceneDirectory["MainMenuScene"]; 
    } 

    public void LoadContent(ContentManager content) 
    { 
     instance.currentScene.LoadContent(content); 
    } 

    public void UnloadContent() 
    { 
     instance.currentScene.UnloadContent(); 
    } 
} 
+2

的可能的复制[什么是一个NullReferenceException,如何解决呢?(http://*.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i -fix-it) – Viru

+0

我知道NullReferenceException是什么,但我的问题是我正在使用有问题的变量,但它仍然给我它。 – user4648142

+1

你是什么意思我使用变量?如何使用变量保证你不会得到空引用异常?无论如何,如果你发布堆栈跟踪,那么你会得到一些代码的哪一部分可能失败的指针....如果你可以调试,那么你甚至可以确定代码行失败....但我没有在你的问题中看到任何这样的信息 – Viru

你声明 Scene为抽象类

,所以你不能仅仅把它作为你正在做的:Scene currentScene, newScene。 (有关抽象类的更多详细信息,请参阅this参考)。

要么使现场非抽象类类型或创建另一个类,从抽象类继承,看你的代码,这将是这样的:

public class myScene : Scene 
    { 
     public override void Update() 
    { 
     //do something 
    } 

    // etc. 

    } 
+0

这是不正确的。你不能*实例化一个抽象类,但是你当然可以拥有一个该类型的变量(并且你应该*有这样的变量,因为这是OOP的全部重点)。 – Groo

你得到一个NullReferenceException因为你是混合在你的代码的静态和实例字段:

有几个问题:

  1. SceneManagerpublic构造函数,但其​​实例方法都访问相同的静态(单例)实例。

  2. 您的SceneManager.Draw方法确实是而不是访问静态实例。

  3. Game类实例化一个单独ScreenManager情况下,这意味着单被初始化,但Game小号实例不是。这是允许的,因为1.

有固定的这几种方式:

的首选方式:从SceneManager删除静态的东西。无论如何,你的游戏将在Game类中有一个实例,你可以简单地将实例传递给任何场景。没有道理。

但是,如果你想保持这个类是一个单例,你需要改变一些东西。人们通常需要这样做,因为他们懒得通过SceneManager到每个场景实例。所以,单身人士是不好的,你不能单元测试任何东西,但我相信大多数独立游戏开发人员不会太在意单元测试,如果一切都是静态的,并且可以从任何地方访问,那么将是最快乐的。

  1. 使构造private,所以没有其他类(如Game)可以实例化。如果有人想访问实例,他们应该通过getInstance()方法来完成。其中,顺便说一句,可能更是一个属性,而不是:

    public class SceneManager 
    { 
        // private constructor means other classes cannot instantiate this 
        private SceneManager() { } 
    
        private static readonly SceneManager _instance = new SceneManager(); 
        public static SceneManager Instance 
        { 
         get { return _instance; } 
        } 
    } 
    

    如果你现在尝试在你的Game类退出这个功能:

    var sceneManager = new SceneManager(); 
    

    你的编译器会告诉你,它不会工作方式。

  2. SceneManager应该只有一个单一静态方法/属性:getInstance()Instance属性等上面显示。所有其他方法应该是该唯一实例的实例方法,并且根本不访问instance字段。无论如何他们正在访问该实例。这是一个坏主意,有实例方法访问静态字段:

    这是错误

    public void Initialize() 
    { 
        var mainScene = = new MainMenuScene(); 
        instance.sceneDirectory["MainMenuScene"] = mainScene; 
        instance.currentScene = mainScene; 
    } 
    

    但这是好的(和this关键字是多余的,当然):

    public void Initialize() 
    { 
        var mainScene = = new MainMenuScene(); 
        this.sceneDirectory["MainMenuScene"] = mainScene; 
        this.currentScene = mainScene; 
    } 
    

    因为你要这样使用它反正:

    // you're basically doing the same thing, but 
    // it's immediately clear what's going on, and there 
    // is no room for errors: 
    
    var manager = SceneManager.Instance; 
    manager.Initialize(); 
    

    最简单的方法可以确保您正确地完成SceneManager类中的所有对instance的引用。