0

I'm trying to learn MonoGame and I'm trying to do basic stuff and I've figured most of it out on my own but I'm getting a null pointer and I'm not sure why. I'm trying to get MainMenuScene to just draw a texture but in SceneManager currentScene keeps giving me null pointers and I have no idea why. Ill post my SceneManager code but the rest will be on github. Its not much code so it shouldnt take long if you'd look over it. I'm super confused and I'm not sure what to google to try to figure it out myself.

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();
    }
}
Thomas Bormans
  • 4,558
  • 5
  • 30
  • 46
  • 2
    Possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Viru Feb 12 '16 at 07:24
  • I know what a NullReferenceException is but my problem is is that I'm using the variable in question yet it still gives me it. – user4648142 Feb 12 '16 at 07:25
  • 1
    what do you mean by I m using variable? how does using variable guarantee that you will not get Null reference exception? Anyway, If you post the stack trace then you will get some pointer of which part of code may be failing....If you can debug then you can even identify line of code which is failing....but I don't see any such information in your question – Viru Feb 12 '16 at 07:34
  • 1
    Obiously you know WHAT an NRE is, but not how to handle and debug it. Thus @Viru provided the helpful link. – HimBromBeere Feb 12 '16 at 07:36
  • If I had to guess I´d say that `instance` is `null` for any reason. You should definitly debug this problemt to check this assumption. I further assume that `instance` is a static member which has never been set within a (private) constructor. But as I said: without debugging this is more a guess than actually knowing. – HimBromBeere Feb 12 '16 at 07:40

2 Answers2

0

you've declared Scene as an abstract class, so you can't just use it as you're doing: Scene currentScene, newScene. (See this reference for more details on abstract classes).

Either make scene a non-abstract class type or create another class that inherits from your abstract class, looking at your code it would be something like:

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

     // etc.

   }
secret squirrel
  • 732
  • 7
  • 12
  • This is not correct. You cannot *instantiate* an abstract class, but you can certainly have a variable of that type (and you *should* have such variables, because that's the whole point of OOP). – Groo Feb 14 '16 at 13:42
0

You are getting a NullReferenceException because you are mixing static and instance fields in your code:

There are several problems:

  1. Your SceneManager has a public constructor, but its instance method all access the same static (singleton) instance.

  2. Your SceneManager.Draw method does not access the static instance.

  3. Your Game class instantiates a separate ScreenManager instance, meaning the singleton is initialized, but the Games instance isn't. This is allowed because of 1.

There are several ways of fixing this:

The Preferred way: remove the static stuff from SceneManager. Your game is going to have a single instance in the Game class anyway, and you can simply pass the instance along to any scenes. A no brainer.

However, if you want to keep this class a singleton, you need to change a couple of things. People usually want this because they are too lazy to pass the SceneManager along to each scene instance. So, singletons are bad, you won't be able to unit test anything, but I believe most indie game developers don't care too much about unit testing and would be happiest if everything was static and accessible from anywhere.

  1. Make the constructor private, so that no other class (like Game) can instantiate it. If anyone wants to access the instance, they should do it through the getInstance() method. Which, btw, might better be a property instead:

    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; }
         }
    }
    

    If you now try to pull this off in your Game class:

    var sceneManager = new SceneManager();
    

    your compiler will tell you it's not going to work that way.

  2. Your SceneManager should only have a single static method/property: getInstance() or the Instance property like shown above. All other methods should be instance methods of that one-and-only instance, and not access the instance field at all. They are accessing that instance anyway. It is a bad idea to have instance methods access static fields:

    This is wrong:

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

    But this is fine (and the this keyword is redundant, of course):

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

    Because you're going to use it like this anyway:

    // 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();
    

    The simplest way to ensure you're doing it right it to remove all references to instance inside the SceneManager class.

Groo
  • 45,930
  • 15
  • 109
  • 179