【问题标题】:MonoGame Window Freezes on dragMonoGame 窗口在拖动时冻结
【发布时间】:2016-07-20 05:57:30
【问题描述】:

我正在 MonoGame 中开发一款联网游戏,并且在拖动窗口时遇到了游戏冻结的问题。在寻找解决方案时,我找到了this answer,它描述了如何注入自定义刻度系统。

但是,虽然此答案适用于 XNA,但所需的反射调用会在 MonoGame 中引发异常。有没有人有替代解决方案可以让游戏在拖动时继续更新?

引发异常的代码段是:

// Exception on this line
object host = typeof(Game).GetField("host", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this);
host.GetType().BaseType.GetField("Suspend", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(host, null);
host.GetType().BaseType.GetField("Resume", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(host, null);

例外情况如下:

在 CardCatacombs.exe 中发生了“System.NullReferenceException”类型的未处理异常

附加信息:对象引用未设置为对象的实例。

据我所知,参考 Game 的“主机”字段。

【问题讨论】:

  • "所需的反射调用在 MonoGame 中抛出异常" 哪个异常?你的代码是什么样的?
  • 可能是你要找的东西:gamedev.stackexchange.com/questions/68914/…
  • 我已经用更多信息更新了我的问题。不幸的是,第二篇文章指的是图形缩放,而不是游戏逻辑更新。
  • 例外是因为Game 对象上不再有host 字段。这可能意味着解开SuspendResume 的第一步是不必要的。您是否尝试过在不执行此第一部分的情况下设置计时器?
  • 在尝试实现计时器时,我注意到 MonoGame 不允许使用 System.Windows.Form.Timer 类。当我尝试从计时器经过的事件(使用 System.Timers.Timer)中调用 Tick() 时,从 Tick() 中抛出“NullReferenceException”错误

标签: c# xna monogame


【解决方案1】:

通过在项目的引用中导入 System.Windows.Forms 程序集并忽略为 XNA 提供的答案的反射组件解决了这个问题,因为 MonoGame 不再使用 Game 中的“主机”字段。

感谢沙华金人的支持。

【讨论】:

    【解决方案2】:

    基于另一个答案,并使用System.Timers.Timer 而不是System.Windows.Forms.Timer

    public class MyGame : Game {
       bool manualTick;
       int manualTickCount = 0;
       Timer mTimer;
    
       public MyGame() {
          mTimer = new Timer {
             Interval = (int)(TargetElapsedTime.TotalMilliseconds)
          };
    
          mTimer.Elapsed += (s, e) => {
             if (manualTickCount > 2) {
                manualTick = true;
                Debug.Print("manual tick");
                Tick();
                manualTick = false;
             }
    
             manualTickCount++;
          };
    
          // required to prevent exception on exit
          // otherwise the timer keeps running after the window closes
          Exiting += (s, e) => mTimer.Dispose();
    
          // it might be needed to do something similar in the Dispose event
          // if the game can be disposed without exiting
       }
    
       // the constructor is too early to start the timer, so put it in initialize
       protected override void Initialize() {
          mTimer.Start();
          base.Initialize();
       }
    
       // and lastly, in Update
       protected override void Update(GameTime pGameTime) {
          if (!manualTick) {
             manualTickCount = 0;
             Debug.Print("not manual");
          }
          base.Update(pGameTime);
       }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多