You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在MonoGame中实现定时金矿生成遇空引用异常,求解决方案

解决MonoGame中计时器的NullReferenceException并实现金矿定时收集功能

嘿,我来帮你搞定这个问题!首先,你遇到的System.NullReferenceException原因很明确——你声明的private GameTime gameTime;字段从来没有被赋值,一直是null状态,当你在CollectGold方法里访问gameTime.ElapsedGameTime时自然就会抛出异常。在MonoGame/XNA中,GameTime是游戏框架在每帧的Update方法里自动传递的,不能自己只声明不赋值就用。

先修复你现有代码的异常

你可以按照下面的步骤修改:

  1. 首先删掉你自己声明的private GameTime gameTime;字段,我们直接用框架提供的GameTime参数
  2. 把计时逻辑移到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:58:32