关于c#:NullReferenceException未处理 – 不明白为什么

NullReferenceException was Unhandled - No idea why

我正在尝试用XNA编写一个非常基本的自顶向下的二维游戏,我已经开始尝试在游戏中添加草地纹理,然后将这些纹理绘制到屏幕的底部。

但是,我的level.cs类的第32行上出现了"NullReferenceException was unmanaged"错误。因为我对XNA还只是个新手(相比之下)对C还比较陌生,所以我无法在我的生活中理解这一点。

更新1:感谢McMonkey4eva,该错误已解决。但是,我的代码现在在testlevel类(level.cs)的draw()方法期间停止。该错误仍然是一个"NullReferenceException was unmanaged"错误,并且方法与以前有点不同。

有人知道我做错了什么吗?

这是我更新的level.cs类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    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.Content;
using First.Tiles;
using First;


namespace First.Level
{
    class TestLevel
    {
        //An array of groundtiles that will be set to grass, lava, etc
        public GroundTile[,] groundlevel;

        //Width/Height of the Level
        int width, height;

        Grass grass;

        public TestLevel(int width, int height, ContentManager myContent)
        {
            content = myContent;
            //I input my screen dimensions as my level size
            this.width = width;
            this.height = height;

            groundlevel = new GroundTile[width, height];

            grass = new Grass(content.Load<Texture2D>(@"Images\GroundTiles"));
        }

        //Drawing the grass near the bottom of the screen
        public void generateGround()
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x += 32)
                {
                    if (y == (height - 100))
                    {
                        if (groundlevel[x, y] == null)
                        {
                            groundlevel[x, y] = grass;
                        }

                    }
                }
            }

        }

        public void draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            foreach(GroundTile ground in groundlevel)
            {
                ground.Draw(gameTime, spriteBatch); //Here's where the error is
            }
        }

        public static ContentManager Content
        {
            get { return content; }
        }
        static ContentManager content;
    }
}

以下是我更新的game1.cs类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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;
using First.Entity;
using First.Tiles;
using First.Level;

namespace First
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {

        const int SCREEN_WIDTH = 600;
        const int SCREEN_HEIGHT = 400;

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        TestLevel level;

        UserControlledSprite Lancer;
        Texture2D lancerTexture;
        Vector2 position = new Vector2(200, 200);
        Point frameSize = new Point(32, 48);
        int collisionOffset = 0;
        Point currentFrame = new Point(0, 0);
        Point sheetSize = new Point(4, 4);
        Point spriteToUse = new Point(0, 0);
        Vector2 speed = new Vector2(2, 2);
        int millisecondsPerFrame = 500;

        Rectangle clientBounds;

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

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            clientBounds = graphics.GraphicsDevice.Viewport.Bounds;
            clientBounds.Width = SCREEN_WIDTH;
            clientBounds.Height = SCREEN_HEIGHT;

            this.IsMouseVisible = true;

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            Content.RootDirectory ="Content";

            level = new TestLevel(SCREEN_WIDTH, SCREEN_HEIGHT, Content);
            level.generateGround();

            lancerTexture = Content.Load<Texture2D>(@"Images\Lancer");
            Lancer = new UserControlledSprite(lancerTexture, position, frameSize, collisionOffset,
                                              currentFrame, sheetSize, spriteToUse, speed, millisecondsPerFrame);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            Lancer.Update(gameTime, clientBounds);

            base.Update(gameTime);

        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            Lancer.Draw(gameTime, spriteBatch);
            level.draw(gameTime, spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

这是我的grass.cs课程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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.Content;
using First.Tiles;
using First;


namespace First.Level
{
    class TestLevel
    {
        //An array of groundtiles that will be set to grass, lava, etc
        public GroundTile[,] groundlevel;

        //Width/Height of the Level
        int width, height;

        Grass grass;

        public TestLevel(int width, int height, ContentManager myContent)
        {
            content = myContent;
            //I input my screen dimensions as my level size
            this.width = width;
            this.height = height;

            groundlevel = new GroundTile[width, height];

            grass = new Grass(content.Load<Texture2D>(@"Images\GroundTiles"));
        }

        //Drawing the grass near the bottom of the screen
        public void generateGround()
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x += 32)
                {
                    if (y == (height - 100))
                    {
                        if (groundlevel[x, y] == null)
                        {
                            groundlevel[x, y] = grass;
                        }

                    }
                }
            }

        }

        public void draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            foreach(GroundTile ground in groundlevel)
            {
                ground.Draw(gameTime, spriteBatch);
            }
        }

        public static ContentManager Content
        {
            get { return content; }
        }
        static ContentManager content;
    }
}

以防万一,这也是我的地砖课:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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.Content;
using First.Entity;

namespace First.Tiles
{
    class GroundTile
    {

        //public GroundTile grass = new Grass(content.Load<Texture2D>(@"Images\GroundTiles"));

        // frameSize needs to be modular, for the objects above walking-ground level

        public Texture2D texture;
        protected Point frameSize;
        public Point frame;
        public Vector2 position;
        int collisionOffset;
        protected Point sheetSize = new Point(9, 19);

        public GroundTile(Texture2D tiles, Point frame, Point frameSize, int collisionOffset)
        {
            this.frame = frame;
            this.frameSize = frameSize;
            this.collisionOffset = collisionOffset;

            this.texture = tiles;
        }

        //Collision Detection, incase of water or something
        public Rectangle collisionRect
        {
            get
            {
                return new Rectangle(
                    (int)position.X + collisionOffset,
                    (int)position.Y + collisionOffset,
                    frameSize.X - (collisionOffset * 2),
                    frameSize.Y - (collisionOffset * 2));
            }
        }

        //Not really used, but just in case
        public bool collidesWith(GroundTile tile, Sprite sprite)
        {
            if (sprite.collisionRect.Intersects(collisionRect))
            {
                sprite.position -= sprite.direction;
            }

            return false;
        }

        public static ContentManager Content
        {
            get { return content; }
        }
        static ContentManager content;

        public GraphicsDevice Graphicsdevice
        {
            get { return graphicsDevice; }
        }
        GraphicsDevice graphicsDevice;

        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture,
                position,
                new Rectangle(frame.X * frameSize.X,
                    frame.Y * frameSize.Y,
                    frameSize.X, frameSize.Y),
                    Color.White, 0, Vector2.Zero,
                    1f, SpriteEffects.None, 0);
        }

    }
}


在设置之前,您正在访问Content,或者,更确切地说,您从未设置过它。

变化

1
2
3
public TestLevel(int width, int height)
{
    //I input my screen dimensions as my level size

1
2
3
4
public TestLevel(int width, int height, ContentManager myContent)
{
    content = myContent;
    //I input my screen dimensions as my level size

然后在创建TestLevel对象时添加content参数(我从game1.cs中假设)(注意:在[在loadcontent方法中]创建content对象之后,一定要创建TestLevel!)

编辑:

对于新问题:

你没有定义数组的内容,除了一层草…

线

1
            ground.Draw(gameTime, spriteBatch);

改为

1
2
3
4
            if (ground != null)
            {
                 ground.Draw(gameTime, spriteBatch);
            }

但你也应该确保这片土地实际上充满了内容…具体来说,数组中每个点的新平铺对象,不仅是一条线,而且不是每个位置的相同"草地"实例。

我不想冒犯你,但你在处理一些基本的错误。您可以查阅并遵循一些基本的C教程。


我不知道XNA,但很明显你很满意。返回NULL。

这是类名称还是级别类的属性?如果它是一个属性,那么确保它已初始化。Otherwize,我不理解如果调用类的静态属性,您将如何收到NullReferenceException