在一个单独的线程中更新物理引擎,这是明智的吗?

时间:2011-05-24 09:55:15

标签: multithreading silverlight xna

我是线程新手100%,作为一个开始我已经决定使用它在一个单独的线程中更新我的物理。我正在使用名为Farseer的第三方物理引擎,这就是我正在做的事情:

// class level declarations
System.Threading.Thread thread;
Stopwatch threadUpdate = new Stopwatch();

//In the constructor:
PhysicsEngine()
{
(...)

            thread = new System.Threading.Thread(
                        new System.Threading.ThreadStart(PhysicsThread));
            threadUpdate.Start();

            thread.Start();
}


        public void PhysicsThread()
        {
            int milliseconds = TimeSpan.FromTicks(111111).Milliseconds;
            while(true)
            {
                if (threadUpdate.Elapsed.Milliseconds > milliseconds)
                {
                    world.Step(threadUpdate.Elapsed.Milliseconds / 1000.0f);
                    threadUpdate.Stop();
                    threadUpdate.Reset();
                    threadUpdate.Start();
                }
            }
        }

这是更新物理的好方法,还是应该注意一些东西?

2 个答案:

答案 0 :(得分:3)

在游戏中,您需要将物理更新与游戏的帧速率同步。这是因为您的渲染和游戏玩法将取决于每帧物理引擎的输出。而且你的物理引擎将依赖于每一帧的用户输入和游戏事件。

这意味着在单独的线程上计算物理的唯一优势是它可以在单独的CPU核心上运行到游戏逻辑和渲染的其余部分。 (这些天对PC来说非常安全,移动空间刚刚开始获得双核。)

这允许它们同时运行物理和游戏/渲染 - 但缺点是你需要有一些机制来防止一个线程在另一个线程使用该数据时修改数据。这通常很难实施。

当然,如果您的物理不依赖于用户输入 - 例如愤怒的小鸟或不可思议的机器(即:用户按下“播放”并且模拟运行) - 在这种情况下它是您可以提前计算物理模拟,记录其输出以进行回放。但是,不是阻止主线程,你可以将这个耗时的操作移动到后台线程 - 这是一个很好理解的问题。甚至在完成录制之前,你甚至可以开始在主线程中播放你的录音!

答案 1 :(得分:1)

一般来说,你的方法没有任何问题。将耗时的操作(例如物理引擎计算)移动到单独的线程通常是个好主意。但是,我假设您的应用程序包含UI中物理对象的某种可视化表示?如果是这种情况,您将遇到问题。

Silverlight中的UI控件具有线程关联性,即您无法在上面示例中创建的线程中更新其状态。为了更新它们的状态,你将不得不通过Dispatcher调用,例如TextBox.Dispatcher.Invoke(...)。

另一种方法是使用Silverlight BackgroundWorker。这是一个有用的小班,可以让你做一些耗时的工作。它会将您的工作转移到后台线程,从而无需创建自己的System.Threading.Thread。它还将为您提供将结果封送回UI线程的事件。

更简单!