我正在尝试学习MonoGame而我正在尝试做基本的事情,而且我已经自己想出了大部分内容但是我得到了一个空指针而且我&# 39;我不知道为什么。我试图让MainMenuScene只绘制一个纹理,但在SceneManager中,currentScene一直给我空指针,我不明白为什么。发布我的SceneManager代码,但其余的将在github上。它的代码不多,所以如果你不看它就不应该花很长时间。我非常困惑,我不知道该怎么去谷歌试图弄清楚自己。
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tutorial.Scenes;
class SceneManager
{
private static SceneManager instance = new SceneManager();
Scene currentScene, newScene;
Dictionary<string, Scene> sceneDirectory =new Dictionary<string, Scene>();
public static SceneManager getInstance()
{
return instance;
}
public static Scene getCurrentScene()
{
return instance.currentScene;
}
public static void changeScene(Scene scene)
{
}
public static void addScene(string sceneName)
{
instance.newScene = instance.sceneDirectory[sceneName];
}
public void update() { currentScene.Update(); }
public void draw(SpriteBatch spriteBatch) { currentScene.Draw(spriteBatch); }
public void Initialize()
{
instance.sceneDirectory["MainMenuScene"] = new MainMenuScene();
instance.currentScene = instance.sceneDirectory["MainMenuScene"];
}
public void LoadContent(ContentManager content)
{
instance.currentScene.LoadContent(content);
}
public void UnloadContent()
{
instance.currentScene.UnloadContent();
}
}
答案 0 :(得分:0)
您已将Scene
声明为抽象类,因此您不能像以前一样使用它:Scene currentScene, newScene
。 (有关抽象类的更多详细信息,请参阅this参考)。
要么使场景成为非抽象类类型,要么创建另一个继承自抽象类的类,查看代码就像:
public class myScene : Scene
{
public override void Update()
{
//do something
}
// etc.
}
答案 1 :(得分:0)
您收到NullReferenceException
,因为您在代码中混合了静态和实例字段:
有几个问题:
您的SceneManager
有公开构造函数,但其实例方法都访问相同的静态(单例)实例。
您的SceneManager.Draw
方法不访问静态实例。
您的Game
类实例化了一个单独的 ScreenManager
实例,这意味着单例已初始化,但Game
的实例并非如此。由于1,这是允许的。
有几种解决方法:
首选方式:从SceneManager
中移除静态内容。无论如何,你的游戏将在Game
类中拥有一个实例,你可以简单地将实例传递给任何场景。没问题。
但是,如果你想让这个班级成为一个单身人士,你需要改变一些事情。人们通常想要这个,因为他们懒得将SceneManager
传递给每个场景实例。所以,单身人士很糟糕,你无法对任何事情进行单元测试,但我相信大多数独立游戏开发者都不太关心单元测试,如果一切都是静态的,并且可以从任何地方访问,那将是最快乐的。
创建构造函数private
,这样其他类(如Game
)就无法实例化它。如果有人想要访问该实例,他们应该通过getInstance()
方法来实现。哪个,顺便说一句,可能更适合作为财产:
public class SceneManager
{
// private constructor means other classes cannot instantiate this
private SceneManager() { }
private static readonly SceneManager _instance = new SceneManager();
public static SceneManager Instance
{
get { return _instance; }
}
}
如果您现在尝试在Game
课程中解决此问题:
var sceneManager = new SceneManager();
你的编译器会告诉你它不会那样工作。
您的SceneManager
应该只有单个静态方法/属性:getInstance()
或Instance
属性,如上所示。所有其他方法应该是该唯一实例的实例方法,而根本不访问instance
字段。无论如何,他们正在访问该实例。让实例方法访问静态字段是个坏主意:
错误:
public void Initialize()
{
var mainScene = = new MainMenuScene();
instance.sceneDirectory["MainMenuScene"] = mainScene;
instance.currentScene = mainScene;
}
但这很好(当然this
关键字是多余的):
public void Initialize()
{
var mainScene = = new MainMenuScene();
this.sceneDirectory["MainMenuScene"] = mainScene;
this.currentScene = mainScene;
}
因为无论如何你都会这样使用它:
// you're basically doing the same thing, but
// it's immediately clear what's going on, and there
// is no room for errors:
var manager = SceneManager.Instance;
manager.Initialize();
确保您正确删除instance
类内SceneManager
所有引用的最简单方法。