1

I've been trying to make a test game in XNA (visual studio 2015), but i get a NullReferenceException every time i load this, even though i actually do initialize it. Here is a very short version of it...

    namespace Overbox
    {
        public class Player
        {
             private Player[] characterList = new Player[14];

             virtual public void Initialize()
             {
                  //characterList = new Player[14];
                  characterList[0] = new Hero();

                  //for (int i = 0; i <= characterList.Length; i++)
                  //    characterList[i].Initialize();
                  characterList[0].Initialize();
             }
    }
    virtual public void Draw(SpriteBatch spriteBatch, Texture2D texture)
    {
        //for (int i = 0; i <= characterList.Length; i++)
        //{
        //    if (characterList[i].Active)
        //        characterList[i].Draw(spriteBatch, texture);
        //}
        characterList[0].Draw(spriteBatch, texture); //Here the error occurs
    }



   }
}

If someone wants the whole class for any reason i could edit this, but this is all the related code i could find.

Edit: stack trace

Overbox.exe!Overbox.Player.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, Microsoft.Xna.Framework.Graphics.Texture2D texture) Line 53 C# Overbox.exe!Overbox.MediaHandler.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) Line 54 C#

Overbox.exe!Overbox.Program.Main(string[] args) Line 15 C#

It's all supposed to be there.

Hero class:

    namespace Overbox.Characters
    {
         class Jacketed : Player
         {
         override public void Initialize()
         {
                //Unrelated setting of variables
         }
         public override void Draw(SpriteBatch spriteBatch, Texture2D texture)
         {
                spriteBatch.Draw(texture, PlayerPosition, Color.White);
         }
    }
}

Very short version of game loop class:

  public class Game1 : Microsoft.XNA.Framework.Game
  {
        public static Player player;
        //I do load the content which playerTexture requires before anyone asks about it
        private Texture2D playerTexture;


        protected override void Initialize()
        {
               player = new Player();
               player.Initialize();
        }
        protected override void Draw(GameTime gameTime)
        {
               spriteBatch.Begin();

               player.Draw(spriteBatch, playerTexture);

               spriteBatch.End();
        }
  }
  • 2
    Where does your NullReferenceException occur? –  Jul 23 '15 at 17:17
  • have you made sure that you are calling `Player.Initialize` before you call Draw? are you sure `spritBatch` and `texture` are not null? – Jason Jul 23 '15 at 17:31
  • @Jason Like i've said in a another post, yes, initialize is called before draw. And spritebatch and texture are not null according to the debugger. – That Martin Guy Jul 23 '15 at 17:42
  • You need to post the stack trace of the exception as well. – Lasse V. Karlsen Jul 23 '15 at 17:49
  • @ThatMartinGuy This new code is not quite complete, since there is no `Texture2D` being passed to `player.Draw`. Please be sure to assemble code which both compiles and shows the problem. – Ken Wayne VanderLinde Jul 23 '15 at 18:34
  • @KenWayneVanderLinde While i know its true, i actually call multiple draw from multiple classes, but other than the fact that i forgot to put the texture in there, it should be, other than the completely unrelated calls and such, the same thing as directly calling it. – That Martin Guy Jul 23 '15 at 18:39
  • @ThatMartinGuy What you should do is copy your project, then start removing code from that project until you get the minimal code which exhibits the problem. Then post the code from this minimal test project so we can see the actual code which causes the problem. These sorts of problems can be hard to diagnose because we overlook certain subtleties. For the same reason, trying to write some code for us on the spot which "should" do the same thing is not sufficient. A direct copy and paste, or else a link to the test code is the best way to get this problem resolved. – Ken Wayne VanderLinde Jul 23 '15 at 19:22
  • Code in the post unlikely to actually reproduce the error. So general guidance on NRE applies (as duplicate). Potentially problem is due to not calling base class' members in overides (i.e. in like `Jacketed` class in the sample). – Alexei Levenkov May 23 '17 at 05:57

3 Answers3

1
private Player[] characterList = new Player[14];

Makes an array of Player, but does not actually construct the objects. So what you end up with is basically an array full of null values.

You are missing something like this:

public Player()
{
    foreach (var character in characterList)
    {
        character = new Player();
    }
}
  • Indeed the NRE has nothing to do with the `Player[]`, but rather its members being `null`. – Arthur Rey Jul 23 '15 at 17:21
  • So are you telling me that i have to construct all the objects that the array requires, even if i only call the one i've constructed? (If you see in the initialize method you can see that im constructing one and only using one) – That Martin Guy Jul 23 '15 at 17:23
  • 2
    The real problem, then, is that `Initialize` is not being called before `Draw`, because he does construct the object in `Initialize`. – Ken Wayne VanderLinde Jul 23 '15 at 17:24
  • Is this an infinite loop? virtual public void Initialize() { characterList[0].Initialize(); } –  Jul 23 '15 at 17:29
  • @KenWayneVanderLinde That might be the problem, but i have no clue why that would be. I only call draw and initialize from the main gameloop class of XNA, which always calls its initialize before draw. – That Martin Guy Jul 23 '15 at 17:29
  • @RobinNadeau Im certain it's not, since "characterList[0].Initialize();" is referring to another class i made which inherits from Player ("Hero"). – That Martin Guy Jul 23 '15 at 17:33
  • It's pretty tough to guess without your class Hero –  Jul 23 '15 at 17:49
0

This is a wild guess, but I'm assuming Hero overrides one or both or Initialize and Draw. Let's say Hero looks like this:

class Hero : Player
{
    public override void Initialize()
    {
        // Do some stuff. Don't call base.Initialize()
    }
}

So we've overridden Initialize(), but haven't called base.Initialize(). We've also not overriden Draw(), so the Draw() from Player will be used when called on a Hero instance.

So let's consider when a Player player is constructed. Then player.characterList is also created, but its elements are null. Next, player.Initialize() is called, setting characterList[0] = new Hero(). Note that characterList[0] has its own characterList array as well.

The next thing to happen is characterList[0].Initialize(). This called the Initialize() override in Hero. This does not call Initialize() inside Player, so the characterList inside the Hero instance still has null elements.

Some time in the future, the Draw method is called in the Player. This, in turn, calls characterList[0].Draw(spriteBatch, texture). Since we didn't override the Draw method in Hero, this calls the same method, but on our Hero instance. But remember that the Hero's characterList still has null values? Well, the only thing to happen here is calling characterList[0].Draw(spriteBatch, texture), which as we now know, is calling Draw on a null value.

This is my guess as to what is happening. The details may vary, but I would imagine this sort of thing is the root cause. To be sure, check the stack trace of the exception. You'll notice two frames for the Draw method, letting you know that the exception occurred in a recursive call to Draw.

Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72
0

I've had this solution in mind for a while, but I didn't want to do it because of organizing reasons. All I had to do was to move characterList to the main game loop class and making it public, guaranteeing that it would be initialized before the draw method would be called. This did work.