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();
        }
  }
8
  • 2
    Where does your NullReferenceException occur? Commented Jul 23, 2015 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? Commented Jul 23, 2015 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. Commented Jul 23, 2015 at 17:42
  • You need to post the stack trace of the exception as well. Commented Jul 23, 2015 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. Commented Jul 23, 2015 at 18:34

3 Answers 3

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();
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Indeed the NRE has nothing to do with the Player[], but rather its members being null.
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)
The real problem, then, is that Initialize is not being called before Draw, because he does construct the object in Initialize.
Is this an infinite loop? virtual public void Initialize() { characterList[0].Initialize(); }
@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.
|
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.

3 Comments

This is not the case. I definetly have overriden the draw method in the hero class, and the stack trace only mentions draw methods it should call, otherwise it wouldn't work.
@ThatMartinGuy Does the overridden Draw method call base.Draw at any point?
@ThatMartinGuy Perhaps posting a minimal Player, Hero and game loop which reproduce the problem would help everyone find the problem.
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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.