【问题标题】:NullReferenceException in xnaxna 中的 NullReferenceException
【发布时间】:2013-03-12 19:41:48
【问题描述】:

我正在尝试创建一个简单的游戏来测试碰撞检测,但它无法正常运行。它构建得很好,但在运行它时出现此错误:“NullReferenceException: Object reference not set to an instance of an object”。

SpriteManager.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Project_3
{
    public class SpriteManager : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private Game1 _Game1;
        //SpriteBatch for drawing
        SpriteBatch spriteBatch;

        //A sprite for the player and a list of automated sprites
        UserControlledSprite player;
        List<Sprite> spriteList = new List<Sprite>();


        public SpriteManager(Game1 game)
            : base(game)
        {
            // TODO: Construct any child components here
            _Game1 = game;
        }

        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        protected override void LoadContent()
        {

            spriteBatch = new SpriteBatch(Game.GraphicsDevice);

            //Load the player sprite
            player = new UserControlledSprite(
                Game.Content.Load<Texture2D>("Images/bill"),
                Vector2.Zero, 10, new Vector2(6, 6));

            //Load several different automated sprites into the list
            spriteList.Add(new AutomatedSprite(
                Game.Content.Load<Texture2D>("Images/kit"),
                new Vector2(150, 150), 10, Vector2.Zero));
            spriteList.Add(new AutomatedSprite(
                Game.Content.Load<Texture2D>("Images/kit"),
                new Vector2(300, 150), 10, Vector2.Zero));
            spriteList.Add(new AutomatedSprite(
                Game.Content.Load<Texture2D>("Images/beast"),
                new Vector2(150, 300), 10, Vector2.Zero));
            spriteList.Add(new AutomatedSprite(
                Game.Content.Load<Texture2D>("Images/beast"),
                new Vector2(600, 400), 10, Vector2.Zero));

            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            // Update player
            player.Update(gameTime, Game.Window.ClientBounds);

            // Update all sprites
            foreach (Sprite s in spriteList)
            {
                s.Update(gameTime, Game.Window.ClientBounds);
            }

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);

            // Draw the player
            player.Draw(gameTime, spriteBatch);

            // Draw all sprites
            foreach (Sprite s in spriteList)
                s.Draw(gameTime, spriteBatch);

            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

引发异常的行是来自SpriteManagerplayer.Update(gameTime, Game.Window.ClientBounds);。完整的异常消息是“Project 3.exe 中发生了类型为 'System.NullReferenceException' 的未处理异常。附加信息:对象引用未设置为对象的实例。”

UserControlledSprite.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Project_3
{
class UserControlledSprite : Sprite
{
    // Movement stuff
    MouseState prevMouseState;

    // Get direction of sprite based on player input and speed
    public override Vector2 direction
    {
        get
        {
            Vector2 inputDirection = Vector2.Zero;

            // If player pressed arrow keys, move the sprite
            if (Keyboard.GetState().IsKeyDown(Keys.Left))
                inputDirection.X -= 1;
            if (Keyboard.GetState().IsKeyDown(Keys.Right))
                inputDirection.X += 1;
            if (Keyboard.GetState().IsKeyDown(Keys.Up))
                inputDirection.Y -= 1;
            if (Keyboard.GetState().IsKeyDown(Keys.Down))
                inputDirection.Y += 1;

            // If player pressed the gamepad thumbstick, move the sprite
            GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
            if (gamepadState.ThumbSticks.Left.X != 0)
                inputDirection.X += gamepadState.ThumbSticks.Left.X;
            if (gamepadState.ThumbSticks.Left.Y != 0)
                inputDirection.Y -= gamepadState.ThumbSticks.Left.Y;

            return inputDirection * speed;
        }
    }

    public UserControlledSprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed)
    {
    }

    public override void Update(GameTime gameTime, Rectangle clientBounds)
    {
        // Move the sprite based on direction
        position += direction;

        // If player moved the mouse, move the sprite
        MouseState currMouseState = Mouse.GetState();
        if (currMouseState.X != prevMouseState.X ||
            currMouseState.Y != prevMouseState.Y)
        {
            position = new Vector2(currMouseState.X, currMouseState.Y);
        }
        prevMouseState = currMouseState;

        // If sprite is off the screen, move it back within the game window
        if (position.X < 0)
            position.X = 0;
        if (position.Y < 0)
            position.Y = 0;
        if (position.X > clientBounds.Width - 150)
            position.X = clientBounds.Width - 150;
        if (position.Y > clientBounds.Height - 150)
            position.Y = clientBounds.Height - 150;

        base.Update(gameTime, clientBounds);
    }
}
}

我不确定为什么它不起作用。我尝试了很多不同的东西,但由于我是 xna 的新手,我可能错过了一些简单的东西。

任何帮助将不胜感激。

编辑:忘记添加 Sprite.cs:

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

namespace Project_3
{
    abstract class Sprite
    {
    // Stuff needed to draw the sprite
    Texture2D textureImage;

    // Collision data
    int collisionOffset;

    // Movement data
    protected Vector2 speed;
    protected Vector2 position;

    // Abstract definition of direction property
    public abstract Vector2 direction
    {
        get;
    }

    public Sprite()
    {
    }

    public Sprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed)
    //: this(textureImage, position, collisionOffset, speed)
    {
    }

    public virtual void Update(GameTime gameTime, Rectangle clientBounds)
    {

    }

    public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
    {
        // Draw the sprite
        if (textureImage != null)
        {
            spriteBatch.Draw(textureImage, position, Color.White);
        }
    }

    // Gets the collision rect based on position, framesize and collision offset
    public Rectangle collisionRect
    {
        get
        {
            return new Rectangle(
                (int)position.X + collisionOffset,
                (int)position.Y + collisionOffset,
                150 - (collisionOffset * 2),
                150 - (collisionOffset * 2));
        }
    }


    public Game1 _Game1 { get; set; }
}
}

【问题讨论】:

  • 尝试 Game.Content.Load("/Images/bill") 注意图像之前的 /
  • Visual Studio 调试器允许您将鼠标悬停在变量上以查看它们的值。这样做,并找出正在取消引用的变量为 null。
  • 'player' 为空。我尝试了一些不同的东西,但我不确定如何调试这样的东西。
  • 您是否确保将播放器纹理添加到内容项目中?然后你确定目录是正确的吗?如果以上所有,试试这个:Game.Content.Load&lt;Texture2D&gt;(@"Images/bill")
  • 设置Game.Content.Load&lt;Texture2D&gt;(@"Images/bill") 修复了该错误,但现在我在Update 方法中的player.Update(gameTime, Game.Window.ClientBounds); 遇到了同样的错误。

标签: c# xna nullreferenceexception


【解决方案1】:

您没有实例化position。您将position 变量传递给UserControlledSprite 的构造函数,但不要将其应用于类范围内的变量。您需要声明另一个变量来保存位置变量,该变量仅对构造函数可见。

这意味着UserControlledSprite对象第一次调用Update,那么position += direction;会抛出NullReferenceException。老实说,我不知道您是如何没有收到编译时错误的,因为position 不会存在于Update 的上下文中,除非您没有向我们展示整个代码。

【讨论】:

  • 我在另一个文件 Sprite.cs 中实例化了position,我最初错误地忽略了它。我已经编辑了原始帖子以添加该文件。
  • 假设代码没有丢失这不是问题(它仍然可能是一个问题)-Sprite 不会在构造函数中调用UpdateUserControlledSprite 也不会。由于在实例化时抛出异常,这不是导致它的原因 - 但它是一个好地方。 Vector2 也不是结构吗?如果是这样,它不会为空
  • 是的 Vector2 是结构,所以位置永远不会为空:msdn.microsoft.com/en-us/library/…
  • 你是对的 Vector2 是一个结构。但是,如果您阅读 cmets,他的问题现在出在 Update 方法上。所以里面有问题。基本上他应该能够进入Update 代码并查看问题出在哪里。同样,其中引用的变量仅在构造方法的上下文中,例如collisionOffset。我认为必须缺少代码,构造函数必须做一些事情,如果 UserControlledSprite 没有通过编译时错误。
  • 我同意,UserControlledSprite 甚至不应该编译。据我所知,Update 方法中没有名为“position”的变量可见。
【解决方案2】:

抱歉,我还不能发表评论。

当您创建播放器(UserControlledSprite)时,您似乎不会从“UserControlledSprite(...parameters...)”调用 Sprite 构造函数。

public UserControlledSprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed)
{
}

可能需要:

public UserControlledSprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed) 
    : base(TextureImage, position, collisionOffset, speed)
{
}

设置您传递的数据也很有用。所以你传入了textureImage、位置、碰撞偏移和速度。我看到您在 Sprite 类中有变量,但我没有看到您在使用构造函数创建它们时设置它们。除非,请告诉我是否是这种情况,传入与变量同名的参数会自动设置它吗?如果不是这种情况,请确保您将 sprite 类中的 position、collisionOffset、speed 和 textureImage 实际设置为它们实际传递的参数。我一直认为参数中的名称不能与类变量中的名称相同。

所以你必须这样做(如果上述情况属实):

public UserControlledSprite(Texture2D _textureImage, Vector2 _position, int _collisionOffset, Vector2 _speed) 
    : base(_textureImage, _position, _collisionOffset, _speed)
{
    //Do this either here or in Sprite. 
    this.textureImage = _textureImage;
    this.position = _position;
    this.collisionOffset = _collisionOffset;
    this.speed = _speed.
}    

我认为上述(紧接在此之上的)细节对于您当前的问题并不那么重要。我认为它与构造函数有更多关系,但我不确定。我这里没有VS,现在只想尝试帮助你。

无论如何,我希望这会有所帮助。对不起,如果可以的话,我会发表评论。可惜我还不能。

【讨论】:

    猜你喜欢
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    • 2010-11-05
    • 2011-07-24
    • 2016-09-20
    • 2013-06-12
    • 1970-01-01
    相关资源
    最近更新 更多