C# ArgumentNullException 未处理 (SpriteBatch.Draw)

C# ArgumentNullException was unhandled (SpriteBatch.Draw)

我实际上是 XNA 的新学生,发现这个库非常有趣,但我仍然缺乏一些知识来进一步学习,因为我觉得我无法自己解决 :(

spriteBatch.Draw() 方法说我的纹理是空的,但是我已经将它加载到 Resources.cs class 中并在 MainMenu.cs 中传递了纹理,所以我真的不知道问题出在哪里,如果有人能帮助我,我将非常感激!

Resources.cs

    class Resources
{
    public static Texture2D pixel;
    public static Texture2D startButton, loadButton, quitButton;

    public static SpriteFont consoleFont;

    public static void LoadContent(ContentManager Content)
    {
        pixel = Content.Load<Texture2D>("Pixel");
        consoleFont = Content.Load<SpriteFont>("Console");

        // UI Ressources :
        startButton = Content.Load<Texture2D>("UI/StartButton");
        loadButton = Content.Load<Texture2D>("UI/LoadButton");
        quitButton = Content.Load<Texture2D>("UI/QuitButton");
    }
}

MainMenu.cs

    class MainMenu
{
    // Fields
    List<Button> buttons = new List<Button>();

    // Constructors
    public MainMenu()
    {
        this.buttons.Add(new Button(new Vector2(480, 132), 256, 48, Resources.startButton));
        this.buttons.Add(new Button(new Vector2(480, 212), 256, 48, Resources.loadButton));
        this.buttons.Add(new Button(new Vector2(480, 292), 256, 48, Resources.quitButton));
    }

    // Methods

    // Update
    public void Update()
    {
    }

    // Draw
    public void Draw(SpriteBatch spriteBatch)
    {
        foreach (Button button in buttons)
        {
            button.Draw(spriteBatch);
        }
    }
}

Button.cs

    class Button : UIElement
{
    int width, height;
    Texture2D texture;

    public Button()
    {
    }

    public Button(Vector2 b_position, int b_width, int b_height, Texture2D b_texture)
    {
        this.position = b_position;
        this.width = b_width;
        this.height = b_height;
        this.texture = b_texture;
    }

    public void Update()
    {
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, position, Color.White);
    }
}

虽然我没有看到您的游戏 class,但我的第一个假设是您从不在资源 class 中调用 public static void LoadContent(ContentManager Content) 方法。由于此函数正在实例化您的纹理,因此可能未调用它。

感谢您的回复! 的确,我忘了包含游戏 class,这是调用资源的正确方法吗?

    public class GameMain : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    MainMenu mainMenu;

    public GameMain()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        this.IsMouseVisible = true;

        mainMenu = new MainMenu();
    }

    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        // TODO: use this.Content to load your game content here
        Resources.LoadContent(Content);
    }

    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        spriteBatch.Begin();
        mainMenu.Draw(spriteBatch);
        spriteBatch.End();
        base.Draw(gameTime);
    }
}

简单真实
你只要知道Game1的函数调用顺序就行了。首先,调用 Game1 的构造函数。那就是你放置 mainMenu = new MainMenu(); 的地方。之后去 InitializeLoad 等等。您必须将 mainMenu = new MainMenu(); 从 Game1 构造函数移动到 Load 函数,在 Resources.LoadContent(Content); 之后,以便可以在 MainMenu 中使用资源之前加载它们。您的 Game1.cs 代码应如下所示:

public class GameMain : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    MainMenu mainMenu;

    public GameMain()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        this.IsMouseVisible = true;
    }

    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        // TODO: use this.Content to load your game content here
        Resources.LoadContent(Content);
        mainMenu = new MainMenu();
    }

    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        spriteBatch.Begin();
        mainMenu.Draw(spriteBatch);
        spriteBatch.End();
        base.Draw(gameTime);
    }
}