0

我希望能够动态更改我的游戏代码。例如,假设我的游戏是这样构造的:

class GameState {
    public int SomeData;
    public Entity[] EntityPool;
}

interface IServices {
    IRenderer Renderer { get; }
}

interface IGameCode {
    void RenderAndUpdate(GameState currentState, IServices serviceProvider);
}

我现在希望能够编写这样的代码:

 void MainLoop() {
    IGameCode gameCode = new DefaultGameCode();
    while(true) {
       // Handle Plattform things
       if(shouldUseNewGameCode) {
          UnloadCode(gameCode);

          gameCode = LoadCode("new.dll");
          // or
          gameCode = LoadCode("new.cs");
       }
       // Call GameTick
       gameCode.RenderAndUpdate(gameState, services);
    }
 }

我已经使用了 AppDomains 和 Proxyclass,但是序列化每一帧太慢了。我试图只传递一个指针,但由于 AppDomains 使用他们自己的虚拟地址空间,我无法访问 GameState 对象。我的另一个想法是使用反射通过 GetMethodBody() 从编译方法中获取 IL 并将其传递给 DynamicMethod 但这会限制我编写 RenderAndUpdate 方法的方式,因为我不能在 IGameCode 实现中使用子方法或变量.

那么我怎样才能实现我想做的事情呢?

4

1 回答 1

0

如您所见,您真的不希望AppDomain在每一帧上都跨越边界,尤其是如果该代码必须回调主代码,例如IServices多次。即使使用MarshalByRefObject可以稍微改善一些情况,它也会太慢。因此,您需要一个不涉及AppDomain.

你的装配有多大?您希望多久更改一次?

注意到 .NET 程序集通常相当节省空间,并且在您的场景中,用户似乎不太可能在会话中多次切换程序集,我只是将您的 DLL 作为 a 读入内存byte[],然后用于Assembly.Load(byte[]);加载它.

或者,如果你真的不能容忍进程内存空间中的死程序集,我认为最好使用辅助进程,也就是“启动器”:当你想切换实现时,启动辅助进程(或者只是如果你愿意,让它一直运行),这反过来将等待当前游戏进程退出,然后将使用新设置启动一个新进程。

这样切换会比较慢,但当然是每次切换的一次性成本,然后程序可以在实际游戏过程中全速运行。

于 2014-12-19T16:17:20.833 回答