在C#中使用动态代码与事件?

时间:2010-12-20 16:00:27

标签: c# events scripting dynamic

我目前正在使用C#“动态”功能编写的游戏中实现脚本引擎。

系统应该如何工作是在调​​用脚本时,它应该注册它侦听的事件,然后将控制权返回给应用程序。然后,当脚本正在侦听的事件被触发时,脚本应该执行。我真的想在脚本引擎中实现的一件事是让具有某些名称的方法自动绑定到事件。例如,onTurnStart()侦听器应自动绑定到turnStart事件。

脚本主要需要执行现有方法并在类中更改变量值;像player.takeDamage()和player.HP = somevalue之类的东西。大多数脚本需要等待玩家转弯的开始和玩家转弯的结束才能被卸载。

复杂的部分是这些脚本需要能够在不对游戏进行任何代码更改的情况下进行更改。 (安全除外)目前的计划是在游戏启动时自动下载所有脚本更改,以确保所有玩家都使用相同版本的脚本。

但是我有三个问题:
1)如何注册和取消注册脚本事件监听器?
2)动态代码可以监听事件吗? 3)(如何)我可以动态注册事件?

这是我第一次使用C#的动态功能,所以任何帮助都将受到赞赏。

感谢
- 迈克尔

1 个答案:

答案 0 :(得分:2)

我不确定你是否拥有动态关键字的正确结束。它本身不允许您在运行时解释新代码。所有这一切都可以让你通过将操作的分辨率延迟到运行时来绕过静态类型检查。

如果您希望“编写”游戏“脚本”,您可能希望了解整合Lua,IronPython或其他DLR语言之一: -

否则,通常要做的事情就是: -

interface IBehavior
{
  // Binds whatever events this behaviour needs, and optionally adds
  // itself to a collection of behaviours on the entity.
  void Register(Entity entity);
}

// Just an example
public abstract class TurnEndingDoSomethingBehavior
{
  public void Register(Entity entity)
  {
    entity.TurnEnding += (s, e) => DoSomething();
  }

  private abstract void DoSomething();
}

问题是,您是否希望能够在编译后添加全新的行为?如果是这样,您需要将部分或全部游戏状态暴露给脚本语言。

或者能够在运行时编写现有行为是否足够?


修改后

说实话,我仍然不确定您对动态关键字和DLR的要求。您的游戏启动器可以下载一个充满行为的类库,就像下载一组脚本一样简单! (这就是Minecraft的发射器在内存服务时所做的事情)

如果您绝对必须使用DLR,请查看我发布的链接。您必须尽可能多地将您的游戏状态暴露给其中一种DLR语言。事件作为一阶函数属性公开。你甚至不需要基本的东西的“动态”关键字。

IronPython中的快速示例: -

def DoSomethingWhenDamageTaken(*args):
  #do whatever...

player.DamageTaken += DoSomethingWhenDamageTaken

玩家类: -

public class Player
{
  public event EventHandler DamageTaken;

  // ...
}

您将其设置为: -

ScriptEngine engine = Python.CreateEngine();
ScriptRuntime runtime = engine.Runtime;
ScriptScope scope = runtime.CreateScope();

// In an actual application you might even be
// parsing the script from user input.
ScriptSource source = engine.CreateScriptSourceFromFile(...); 

Player p = new Player();
scope.SetVariable("player", p);
source.Execute(scope);

一些可以帮助您入门的链接: -