在MonoGame中实现定时金矿生成遇空引用异常,求解决方案
解决MonoGame中计时器的NullReferenceException并实现金矿定时收集功能
嘿,我来帮你搞定这个问题!首先,你遇到的System.NullReferenceException原因很明确——你声明的private GameTime gameTime;字段从来没有被赋值,一直是null状态,当你在CollectGold方法里访问gameTime.ElapsedGameTime时自然就会抛出异常。在MonoGame/XNA中,GameTime是游戏框架在每帧的Update方法里自动传递的,不能自己只声明不赋值就用。
先修复你现有代码的异常
你可以按照下面的步骤修改:
- 首先删掉你自己声明的
private GameTime gameTime;字段,我们直接用框架提供的GameTime参数 - 把计时逻辑移到
Update方法里(或者让CollectGold接收GameTime参数,在Update里调用它时传入)
修改后的代码示例:
int counter = 1; int limit = 50; float countDuration = 5f; // 改成你需要的5秒间隔 float currentTime = 0f; private int mGold = 0; private int mMaxGold = 100; // 示例初始金矿上限 protected override void Update(GameTime gameTime) { // 在这里处理时间累积逻辑 currentTime += (float)gameTime.ElapsedGameTime.TotalSeconds; if (currentTime >= countDuration) { counter++; currentTime -= countDuration; CollectGold(); } base.Update(gameTime); } private void CollectGold() { // maxGold limits the Mine if (mMaxGold > 0) { mGold += 5; mMaxGold -= 10; // 这里可以添加UI更新或者日志输出逻辑 } }
更优雅的计时器实现方式
如果你的游戏里有多个计时需求,封装一个可复用的GameTimer类会更方便,代码也更整洁:
public class GameTimer { private float _elapsedTime; private readonly float _interval; private readonly Action _onTrigger; private bool _isActive; public GameTimer(float interval, Action onTrigger) { _interval = interval; _onTrigger = onTrigger; _isActive = true; } public void Update(GameTime gameTime) { if (!_isActive) return; _elapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; // 用while处理时间累积超过多个间隔的情况(比如游戏暂停后恢复) while (_elapsedTime >= _interval) { _onTrigger?.Invoke(); _elapsedTime -= _interval; } } public void Start() => _isActive = true; public void Stop() => _isActive = false; public void Reset() => _elapsedTime = 0; }
使用这个计时器的示例
在你的游戏类里这样用:
private GameTimer _goldTimer; protected override void Initialize() { // 初始化一个5秒触发一次的金矿收集计时器 _goldTimer = new GameTimer(5f, CollectGold); base.Initialize(); } protected override void Update(GameTime gameTime) { _goldTimer.Update(gameTime); base.Update(gameTime); } private void CollectGold() { if (mMaxGold > 0) { mGold += 5; mMaxGold -= 10; } else { // 金矿耗尽,停止计时器 _goldTimer.Stop(); } }
这种方式的好处是:
- 代码解耦,计时逻辑和业务逻辑分开
- 可以轻松创建多个不同的计时器(比如其他资源的收集、技能冷却等)
- 自带启动、停止、重置功能,更灵活
内容的提问来源于stack exchange,提问作者Arenosa
相关产品推荐
相关产品推荐

