在C#中创建AI行为树 - 如何?

时间:2010-11-22 02:43:23

标签: c# artificial-intelligence

我正在尝试使用C#创建一个“行为树”。

对于任何不知道的人,行为树基本上是一个可以构建AI的框架。有顺序器,选择器,装饰器,复合动作等。

我找到了一个单独的库,它在C#中建立了一个“行为树”,位于这里(http://code.google.com/p/treesharp/)但我无法理解如何实际使用它,因为我没有可以从中抽取的示例代码。这里的任何人都可以制作一些简单的示例代码来说明如何实际使用这个框架..或者你可能知道在C#中使用行为树的另一种方式?

非常感谢!

3 个答案:

答案 0 :(得分:14)

我只是看了一下这个实现,我发现自己想知道为什么这么多代码需要相对简单的东西。

根据您的说法,您需要一种简单的组合行为方式。我认为,这里的行为是代理从状态到零或更多动作的映射。您可以使用C#lambdas轻松地对此进行建模。例如:

Action Selector(Func<bool> cond, Action ifTrue, Action ifFalse) {
  return () => { if cond() then ifTrue() else ifFalse() };
}

Action Sequencer(Action a, Action b) {
  return () => { a(); b(); }
}

树的叶子是简单的动作,可以做一些适合于州的事情。只需执行它即可“运行”一棵树。

如果你想获得幻想,你可以参数化这个方案,使状态明确。

希望这有帮助。

----附录----

Jason问了一个如何使用这种方法的例子,所以这里是一个简单的“AI”巡逻守卫示例(我假设WorldState对应于行为树评估时的环境描述):

Func<bool> ifPlayerIsInSight = () => ...true iff WorldState shows guard can see player...;

Action shootAtPlayer = () => { ...aim guard's weapon at player and fire... };

Func<bool> ifUnderFire = () => ...true iff WorldState shows guard hears player gunfire...;

Action takeCover = () => { ...guard runs for nearest shelter... };

Action walkBackAndForthGuardingDoorway = () => { ...default guard patrol behaviour... };

Action patrollingGuardBehaviour =
  Selector(ifPlayerIsInSight, shootAtPlayer,
    Selector(ifUnderFire, takeCover,
      walkBackAndForthGuardingDoorway));

要让警卫做某事,只需致电patrollingGuardBehaviour()。请注意,各种子动作和测试可以实现为具有正确签名的方法,而不是内联为lambdas。您可以将其他组合符添加到SelectorSequencer,例如,用于并行活动。

答案 1 :(得分:4)

看起来TreeSharp背后的开发人员apocdev有一些code that uses TreeSharp for some kind of spell-casting World of Warcraft player

这是一个snippit:

public Composite CreateSpellCheckAndCast(string name)
{
    return new Decorator(
        ret => Spells.CanCast(name),
        new Action(ret => Spells.Cast(name)));
}

我不确定,但这里的用法看起来很简单:Decorator类看起来像在尝试执行某个操作(Spells.CanCast)之前检查谓词(Spells.Cast

因此,Composite可能是Action,可以执行多项操作,例如事先检查一个谓词或按顺序执行几个动作。

apocdev's blog提及this overview of behavior trees,其中包含sequencesselectorsdecorators的更一般说明。

答案 2 :(得分:2)

C#lambda在涉及闭包时会变得昂贵,因为这会导致BT的每个帧/迭代出现分配。 您可以使用黑板来避免闭合,但是有一种更简单的方法。

您可以使用短路条件运算符<input>$('#AccountCodeTable tbody tr').each(function (i) { $(this).find('input').attr('name', function () { return this.name.replace(/\d+/, i); }); }); 来实现行为树。 此处说明了这种方法: https://github.com/eelstork

然后巡逻示例如下:

&&