生物AI

来自Minecraft Wiki
跳转到导航 跳转到搜索

在Minecraft中有各种各样不同的生物,它们都有独特的行为,而这些行为由生物AI系统计算与调控。持有生物AI的生物被称为AI生物

概述[编辑 | 编辑源代码]

生物AI系统根据生物当前的状态State)、所处的环境(Environment),计算现在应该做的事情,并通过各种控制器Control)将这些动作命令变为实际的操作,达到表观上的控制生物。

在游戏中,有两种生物AI系统用于生物行为计算,而这两种系统都遵循上面的方式控制生物。它们分别为:

  • 意向系统:通过意向选择器Goal Selector)挑选生物当前的“意向”,从而控制生物。
  • 记忆行为系统[仅Java版]:存储生物的记忆Memory),根据当前的活动Activity),与状态、环境一起计算出生物当前的所有行为Behavior Control),从而控制生物。

意向系统[编辑 | 编辑源代码]

意向系统中,意向Goal)是控制生物的基本单位。

运行频率[编辑 | 编辑源代码]

基岩版中,意向系统每游戏刻都会计算,已启动的意向也会在每个游戏刻执行。

Java版中,意向系统的执行状态在每个游戏刻会有所不同。游戏会让当前维度的游戏刻计数(不是游戏时间,而是服务器启动到现在的游戏刻数量)与实体ID值相加,并进行判断:

  • 如果计算结果是偶数,则正常进行意向系统计算,并执行已启动的意向。换言之,意向系统每2个游戏刻计算一次,尝试启动满足条件的意向。
  • 如果计算结果是奇数,则意向系统不进行计算,但会执行部分已启动的意向。在意向系统不计算时执行是部分意向的属性,许多意向并不具有这个属性,所以无法在每个游戏刻执行。

意向分类[编辑 | 编辑源代码]

意向根据作用可以分为两类:

  • 动作意向:这类意向控制了生物的具体动作,比如随机游走、攻击、逃跑等动作。
  • 索敌意向Target Goal):这类意向控制了生物的攻击对象,比如主动将玩家视为攻击对象,或将攻击自身的生物作为攻击对象。

动作意向又被进一步细分。每个动作意向都具有它们会控制生物哪种控制器的旗标Flag)。一个动作意向可以控制一种控制器,比如移动控制器;也可以控制多个控制器,比如移动、视角控制器。旗标一共有下列三种:

  • 移动Move):动作意向使用移动控制器Move Control)进行寻路计算并使得生物根据指定路径行进。
  • 视角Look):动作意向使用视角控制器Look Control)移动生物的视角。
  • 跳跃Jump):动作意向使用跳跃控制器Jump Control)使生物主动跳跃或阻止被动跳跃。

意向生命周期[编辑 | 编辑源代码]

每个意向的执行过程都有固定的顺序,按照先后分别为:

  1. 生物被加载或生成,意向被创建(Construct)。
  2. 满足启动条件,被启动(Start)。
  3. 满足运行条件,被执行(Tick)。
    • Java版中,如果意向可以被持续计算,则在每个游戏刻都可以被执行。
  4. 不满足运行条件或被其他意向替代,被停止(Stop)。

基岩版中,意向至少会被执行一次。在Java版中,意向可能无法被执行,而只被启动和停止。

部分意向不允许被替代,即意向在运行时不允许被更高优先级的其他意向打断。这种意向的停止只可能为自身不满足运行条件。

选择与执行意向[编辑 | 编辑源代码]

意向系统计算选择意向和执行意向按照下列步骤执行:

  1. 停止当前不能执行的索敌意向。
  2. 挑选并启动可以执行的索敌意向。
  3. 运行当前的索敌意向。
  4. 停止当前不能执行的动作意向。
  5. 挑选并启动可以执行的动作意向。
  6. 运行当前的动作意向。

Java版中,在有些时间内意向系统不会计算(见上文),只会执行意向,此时的执行步骤为:

  1. 运行当前可以持续计算的索敌意向。
  2. 运行当前可以持续计算的动作意向。

停止意向[编辑 | 编辑源代码]

当意向满足下列条件的任何一个,在意向系统计算时它就会被立刻停止:

  • 意向已经执行完毕,等待停止。
  • 对于动作意向,动作意向的旗标中,有一个旗标对应的控制器被禁用。
  • 对于索敌意向,索敌控制器被禁用。
  • 意向不满足自身的运行条件,需要被停止。

挑选索敌意向[编辑 | 编辑源代码]

对于索敌意向,如果索敌控制器没有被禁用,意向系统才会选择索敌意向。

Java版中,对于所有索敌意向,都会进行下列的挑选步骤:

  1. 如果索敌意向不满足启动条件,则忽略。
  2. 如果索敌意向为当前运行的索敌意向,则忽略。
  3. 如果索敌意向优先级低于当前运行的索敌意向的优先级,则忽略。如果当前没有运行的索敌意向,则可以进入下一步骤。
  4. 如果当前有运行索敌意向,则将当前运行的索敌意向强制停止。
  5. 启动选择的索敌意向,并把这个索敌意向作为当前运行的索敌意向。

基岩版中,挑选索敌意向只需要找出满足启动条件的最高优先级索敌意向,并与当前运行的索敌意向进行优先级比较。如果当前运行的索敌意向优先级更高则不会发生任何改变;反之,当前运行的索敌意向会被停止,新的索敌意向会被启动,并作为当前运行的索敌意向。

Java版基岩版的挑选过程虽然有所不同,但在执行上效果基本一致。Java版中索敌意向基本上都以高优先级到低优先级定义,所以阻止了低优先级多次逐渐被高优先级替代而造成多次停止和启动索敌意向的情况。

挑选动作意向[编辑 | 编辑源代码]

对于动作意向,挑选行为更加复杂,以适应多种情形。运行的动作意向可以不止一个,这一点与索敌意向不同。

动作意向之间会产生冲突,而冲突的来源是使用了同一个控制器,即含有相同的旗标。为防止动作意向冲突,每个旗标最多只能有一个动作意向,不同的旗标间没有关系,可以存在多个动作意向。如近战攻击意向有移动和视角旗标,躲避其他实体有移动旗标,那么它们就不能共存,因为它们同时都有移动旗标;看向玩家意向只有视角旗标,那么它和躲避其他实体意向就可以共存,因为它们不含有同样的旗标。

如果一个动作意向正在运行,它会占用它含有的旗标,以确保其他动作意向不会和它产生冲突。

Java版中,对于所有动作意向,都会进行下列的挑选步骤:

  1. 如果动作意向不满足启动条件,则忽略。
  2. 如果动作意向当前正在运行,则忽略。
  3. 如果动作意向使用了被禁用的控制器,则忽略。
  4. 对于动作意向的所有旗标:
    • 如果没有动作意向占用此旗标,则这个旗标检查成功,可以继续检查。
    • 如果有动作意向占用此旗标,则检查此动作意向和占用旗标的动作意向的优先级。如果此动作意向优先级高于占用旗标的动作意向,且占用旗标的动作意向可以被中断,则这个旗标检查成功,继续检查其他旗标;否则,这个动作意向无法被启动,剩余步骤被跳过。
  5. 对于这个动作意向含有的所有旗标,停止原先占用这些旗标的动作意向,启动此动作意向。

基岩版中,挑选动作意向就是找到可以启动且标签不冲突的最高可能优先级动作意向集合。如果集合和当前运行的动作意向集合相同,则不会进行启动和停止;反之,停止未在动作意向集合内的动作意向,启动动作意向集合内未运行的动作意向。

Java版基岩版的挑选过程虽然有所不同,但在执行上效果基本一致。主要的区别在于动作意向在定义时如果不按照优先级排序,那么在Java版中一个动作意向可能被启动后立刻被中断被其他动作意向替代。

举例[编辑 | 编辑源代码]

下面以Java版史莱姆举例,分析它的AI行为。下表是史莱姆的索敌意向和动作意向:

优先级 索敌意向 动作意向
视角 移动 跳跃
1 锁定最近玩家
Nearest Attackable Target Goal <Player>
在液体内上浮
Slime Float Goal
2 视角转向攻击
Slime Attack Goal
3 锁定最近铁傀儡
Nearest Attackable Target Goal <IronGolem>
随机视角转向
Slime Random Direction Goal
5 持续跳跃移动
Slime Keep On Jumping Goal

首先分析索敌意向。史莱姆只会主动攻击两种生物:玩家和铁傀儡,且玩家的优先级更高,即史莱姆更偏向于攻击玩家。如果史莱姆周围有符合条件的铁傀儡和玩家,那么史莱姆会把玩家作为攻击对象而不是铁傀儡。同时,史莱姆没有反击索敌意向,这代表了它不会去攻击刚才攻击它的生物,这使得游戏内无法让史莱姆主动攻击其他生物。

再分析动作意向。史莱姆一共有4个动作意向:

  • 在液体内上浮:这个动作意向的启动条件和运行条件是史莱姆处于熔岩内。动作是史莱姆每游戏刻有80%的概率跳跃(即上浮),并向前行进。
  • 视角转向攻击:启动条件和运行条件是锁定了一个攻击对象。动作是史莱姆会看向攻击对象。
  • 随机视角转向:启动条件和运行条件是没有攻击对象。动作是每40-100游戏刻随机转向一次。
  • 持续跳跃移动:启动条件和运行条件是史莱姆不骑乘其他实体。动作是向前行进。

当史莱姆没有攻击对象时,运行的意向只有两个:随机视角转向和持续跳跃移动,此时史莱姆会随机地跳动行进。但当史莱姆有攻击对象时,随机视角转向意向不满足运行条件被停止,视角转向攻击意向被启动,使史莱姆看向攻击目标,而持续跳跃移动意向又使得史莱姆向前行进,达到接近并接触伤害攻击目标的效果。如果史莱姆落入水中,则持续跳跃移动意向被在液体内上浮意向替代,使得史莱姆跳跃上浮不至于在水中窒息而死。

再以Java版苦力怕举例,下表是苦力怕的索敌意向和动作意向:

优先级 索敌意向 动作意向
视角 移动 跳跃
1 锁定最近玩家
Nearest Attackable Target Goal <Player>
在液体内上浮
Float Goal
2 锁定伤害自身生物
Hurt By Target Goal
膨胀爆炸
Swell Goal
3 远离豹猫
Avoid Entity Goal <Ocelot>
远离
Avoid Entity Goal <Cat>
4 近战攻击
Melee Attack Goal
5 随机游走(避免接触水)
Water Avoiding Random Stroll Goal
6 看向玩家
Look At Player Goal
随机视角
Random Look Around Goal

先看索敌意向。苦力怕优先将玩家作为攻击对象,其次为反击攻击它的生物。如果一个苦力怕被其他生物伤害,苦力怕会尝试去反击攻击它的生物,但如果玩家在附近,则会选择玩家作为攻击对象,放弃反击攻击它的生物。

再分析动作意向。苦力怕只有一个动作意向会占用跳跃旗标:在液体内上浮意向。这使得苦力怕可以在任何情况下主动上浮不至于在水中溺亡。其他的动作意向的条件和作用如下:

  • 膨胀爆炸:启动条件和运行条件是苦力怕已经开始膨胀或距离攻击目标3格以内,动作是进行膨胀并发生爆炸,也负责收缩停止爆炸。
  • 远离生物:启动条件是以苦力怕碰撞箱水平各扩展6格,上下各扩展3格范围内有豹猫或猫,且苦力怕可以找到一个远离对应生物的位置并可以寻路到对应位置。运行条件是当前逃离路径没有走完。主要动作就是沿着找到的逃离路径快速远离对应生物。
  • 近战攻击:启动条件是苦力怕锁定了一个攻击对象,且可以到达攻击对象身边。运行条件是攻击对象没有失踪或死亡,且当前走向攻击对象的路径没有走完。主要动作是苦力怕跟随攻击目标,并进行近战攻击
  • 随机游走:启动条件是苦力怕没有被任何实体骑乘,且无动作计数器不大于100,平均120游戏刻(6秒)随机游走一次。运行条件是苦力怕没有被任何实体骑乘,且当前游走路径没有走完。
  • 看向玩家:启动条件是苦力怕有攻击对象或以苦力怕碰撞箱水平各扩展8格,上下各扩展3格范围内有玩家,平均100游戏刻(5秒)看向这些生物一次。运行条件是看向的生物没有死亡,且距离苦力怕8格以内。动作是苦力怕转向这些生物,持续时间为40-80游戏刻。
  • 随机视角:启动条件只有一个随机判定,平均100游戏刻(5秒)看向随机方向一次。动作是苦力怕转向一个方向,持续时间为20-40游戏刻。

如果苦力怕没有攻击目标且附近没有猫或豹猫,那么上述动作意向中只有随机视角意向和随机游走意向可以启动和运行。如果苦力怕先启动了随机视角意向,又满足了随机游走意向条件,那么随机视角意向会被立刻中断,随机游走意向会替代它运行。这两个动作意向无法共存,因为它们都占用了视角和移动旗标。

如果苦力怕周围有创造模式玩家,苦力怕虽然不能把创造模式玩家作为攻击对象,但是可以看向它。看向玩家意向和随机视角意向也不能共存,因为它们都占用视角旗标,但是这两个意向不能打断对方,因为它们处于同一优先级,一个意向必须等待另一个意向将旗标释放才可以运行,而不能强制停止另一个意向。同时,因为看向玩家意向比随机视角意向更先定义,代表看向玩家意向会先判断是否启动,所以看向玩家意向启动的概率会稍高于随机视角意向。

如果苦力怕有攻击对象,且距离3格以上,此时近战攻击意向会被启动,使得苦力怕追踪攻击对象,接近攻击对象。当距离攻击对象3格以内时,更高优先级的膨胀爆炸意向会被启动,开始膨胀并最终爆炸。虽然苦力怕有近战攻击意向,而且也有基础近战攻击力,但是苦力怕不会真正进行近战攻击,因为膨胀爆炸意向的优先级高于近战攻击,苦力怕在到达可以近战攻击生物的范围时近战攻击意向已经膨胀爆炸意向替代,而这里近战攻击意向的作用仅是让苦力怕靠近攻击对象。如果在近战攻击意向途中附近有猫或豹猫,那么近战攻击意向也会被远离生物意向替代,使得苦力怕放弃追踪攻击对象而远离猫和豹猫。但如果苦力怕逃离的过程中距离攻击对象3格以内,那么它会立刻停止逃离并开始膨胀爆炸。

记忆行为系统[编辑 | 编辑源代码]

本段落所述内容仅适用于Java版

记忆行为系统是一套更加复杂的AI系统。Java版1.16之后加入的生物(炽足兽、发光鱿鱼、沼骸除外)和村民使用此AI系统,而其他生物仍然使用意向系统。

记忆行为系统与意向系统不同,它在每个游戏刻都会计算。虽然记忆行为系统更新得更加频繁,提升了生物的智能,但也加大了AI计算的负担。

记忆行为系统分为三个重要的组件:记忆、行为与活动。

记忆[编辑 | 编辑源代码]

参见:生物记忆

生物具有许多状态,包括当前的位置、攻击对象等,而记忆是生物状态的一种扩充。记忆包含三个属性:

  • 记忆类型Memory Module Type):这条记忆存储了什么数据和这条记忆的作用。
  • 记忆值Memory Value):当前记忆存储的数据。记忆值可以为各种数字,也可以为一个对象,比如一个方块位置或实体。
  • 存活时间Time To Live, TTL):记忆在这段时间内才是有效的,超出这段时间记忆就会无效并被删除。部分记忆没有存活时间。

根据是否可以存储到生物数据中,记忆分为两类:短期记忆和长期记忆。短期记忆无法存储到生物数据中,当生物被卸载时数据丢失;长期记忆可以存储到生物数据中,在卸载后再加载可以维持之前的计算状态。

记忆和所对应的记忆类型通常会经历下面的生命周期:

  1. 生物被加载或生成,记忆类型被注册Register),但相应的记忆不存在。
  2. 生物通过感受器Sensor)获取环境中的信息,或通过行为产生数据,并将这些值作为记忆存储到生物内。此时生物就获得了相应的记忆。
  3. 如果一个记忆具有存活时间,当记忆超出存活时间时,记忆过期Expire)而被删除。
  4. 如果感受器或行为决定这个记忆不再有效,则记忆被抹除Erase)。

感受器[编辑 | 编辑源代码]

感受器是生物从环境获取信息的一种方式,在获取后存入生物记忆中。

感受器并不是每个游戏刻都执行,它有固定的扫描速率Scan Rate),通常为20游戏刻(1秒)。

感受器基本可以分为两类:

  • 生物感受器:生物会根据各种目标搜索条件Target Condition)检查附近的生物,并将符合条件的生物存到对应的记忆中。
  • 状态感受器:生物根据当前的位置和周围情况,将信息存储到对应的记忆中。

绝大多数感受器都是生物感受器,主要用于索敌,也用于一些其他生物AI计算。

为了让行为能有足够的信息用于执行,感受器永远都在行为之前运行,以提供需要的信息。

行为[编辑 | 编辑源代码]

行为与意向类似,代表了生物的一个具体动作,但这个动作除了使用视角、移动、跳跃控制器外,还可以控制记忆。行为与意向的最大区别是:意向不可以互相组合,但行为可以组合并形成复杂的组合行为。

行为通常会经历下面的生命周期:

  1. 生物被加载或生成,行为被创建(Construct)。
  2. 当行为所在的活动正在运行且行为没有运行时,尝试启动(Try Start)。尝试启动可能成功也有可能不成功,如果成功则行为开始运行,如果不成功则不运行。
  3. 如果行为正在运行,则每个游戏刻都会执行或尝试停止(Tick Or Stop)。
  4. 其他行为或当前的某些情况可以使行为被强制停止(Do Stop)。

按照上述生命周期和实际动作的不同,行为被划分为四类:

  • 持续行为Behavior):生物在一段时间内持续进行的行为。
  • 无行为Do Nothing):生物在一段时间内不做动作。
  • 门行为Gate Bahavior):挑选一系列子行为执行。
  • 单刻行为One Shot)/触发器行为Trigger):生物在满足指定条件时触发此行为,之后立刻停止。

持续行为[编辑 | 编辑源代码]

持续行为的动作会持续一段时间。根据行为的基础生命周期,持续行为继续细化生命周期:

  • 尝试启动:持续行为的启动条件分为两部分,即记忆检查Required Memories)和额外启动条件Extra Start Conditions)。
    • 记忆检查即对生物当前拥有的记忆进行检查。记忆共有三种可能状态:注册、存在和不存在。如果要求记忆注册,只要生物注册了这个记忆类型不管记忆是否存在都算检查成功。
    • 额外条件检查因行为不同而异,通常为检查生物状态和记忆值。
  • 执行或尝试停止:持续行为能否一直运行也需要进行两部分检查,即超时检查Timed Out)和额外运行条件Can Still Use)。如果前两项检查有一项不通过,那么持续行为就会停止,否则继续执行。
    • 每个持续行为都有它们的最大运行时长或运行时间范围,通常为60游戏刻(3秒)。如果一个持续行为已经达到了最大运行时长,那么这个行为超时,自行停止。
    • 额外运行条件由各个持续行为自身定义。

无行为[编辑 | 编辑源代码]

无行为代表这个行为什么都不做。它没有启动条件,尝试启动无行为会立刻生效。无行为在持续指定时间后就会自行停止。

虽然名称叫无行为,但是它不代表生物在这段时间内真的什么都不做。无行为只是代表生物进行这个行为时这个行为不会产生动作,而其他的行为仍然有可能启动、运行和停止,在表现上生物不会突然停止。

门行为[编辑 | 编辑源代码]

门行为可以挑选内部的子行为启动和执行,类似于一个简易版的意向选择器。

门行为的启动条件只有一个,即记忆检查(见上文)。如果启动成功,门行为就会对内部的子行为进行判断,并启动子行为。

门行为内维护了一个带权重的子行为列表,当门行为启动时,这个列表会进行重新排序,以随机调整行为尝试启动顺序。重新排序方式分为两种:

  • 维持原顺序Ordered):不对列表进行重新排序,维持定义时的顺序。
  • 按权重打乱Shuffled):使用每个列表项的权重对列表重新排序,权重越大,排序之后就越有可能在列表前方。如果一个子行为列表项权重为w,门行为对这个子行为项的随机数为r(范围为[0,1)),则排序数r=r1w,之后门行为对这些子行为项按排序数从小到大排序,使得权重越大的项排序越靠前。

当重新排序结束后,门行为会对列表按顺序尝试执行,执行有两种情况:

  • 仅启动第一个Run One):门行为按照顺序尝试启动子行为,直到成功启动了一个子行为,后续子行为不会被启动。
  • 尝试全部启动Try All):门行为按照顺序尝试启动全部子行为,使得可以存在多个子行为一起启动。

门行为只会在自身启动时尝试启动子行为。当门行为被执行时,所有运行的子行为也会被执行,当子行为全部停止后门行为也会自行停止。如果门行为被强制停止,其子行为也会被强制停止。

单刻行为[编辑 | 编辑源代码]

单刻行为只会运行1游戏刻,之后立刻停止。当单刻行为尝试启动时,游戏检查这个单刻行为对应的条件,如果条件检查成功则启动运行行为内容,如果未通过则不执行。当行为执行或尝试停止时,单刻行为立刻停止,使得单刻行为只会运行1游戏刻。

生物的很多行为都不需要持续进行,只需要对记忆进行修改,再通过一些基础的持续行为读取这些记忆执行相应的动作。例如生物随机游走到一个位置,只需要检查当前行走目标记忆是否存在,如果不存在那么就有一定概率随机找到一个随机游走位置,并将行走目标记忆定位到那里,之后立刻停止。在之后的走向行走目标行为会读取这个记忆,进行持续动作。这种做法可以减少行为之间的冲突,也可以减少计算负担。

活动[编辑 | 编辑源代码]

当各种各样的行为组合在一起时,就组成了活动。每个行为必须绑定或者间接绑定一个活动。

活动中定义的行为也具有优先级,但这个优先级并不是对于活动内定义的,而是对于所有活动定义的。如果活动A有一个优先级为2的行为a,活动B有一个优先级为1的行为b,那么游戏会先尝试启动行为b再启动行为a。

活动有两种状态:激活Active)和未激活Inactive)。未激活的活动内部的行为不可以被启动,激活的活动内部的行为可以被启动,而行为的执行和停止和活动的当前状态无关。激活通常都会检查一定的激活要求,如果不满足活动就无法激活。活动在取消激活时可能会抹除一定的记忆,用于消除活动的数据。

每个生物都有一系列核心活动Core Activities)和一个默认活动Default Activity)。核心活动不会被取消激活,永久处于激活状态用于维持生物最基础的行为,比如按路径行走这类行为。除核心活动外,其他活动只能被激活一个。如果生物尝试激活一个活动,则需要先取消激活所有非核心活动。如果激活活动时对应活动不满足激活要求,则自动激活默认活动。

活动的激活通常由行为或生物发生的事件而修改,但还有一种特殊的活动切换,即时刻表Schedule),使得活动可以按照当前的游戏内一天中的时间计算生物应该激活什么活动。目前只有村民会使用时刻表计算当前的激活活动。

系统执行流程[编辑 | 编辑源代码]

将所有记忆行为系统的组件组合起来,每个游戏刻系统执行流程主要分为四个阶段:

  1. 删除已经过期的记忆。
  2. 尝试运行所有感受器。
  3. 尝试启动所有未启动的行为。
  4. 执行并尝试停止所有正在运行的行为。

删除过期记忆[编辑 | 编辑源代码]

在这个阶段,生物现在的所有记忆都需要进行计算。如果一个记忆没有存活时间,则代表这个记忆不会过期,计算被忽略。如果记忆有存活时间,那么先判断记忆是否过期,之后再将记忆的存活时间减少1游戏刻。

由于记忆删除和存活时间减少的顺序,实际删除过期记忆的时间比存活时间值本身要多出1游戏刻:假设在第0游戏刻生物获得记忆A,且存活时间为600游戏刻,由于删除过期记忆在所有记忆写入之前,所以第0游戏刻不会减少存活时间。在之后的600游戏刻内,存活时间逐渐减少但没有到达0,所以记忆不会被删除。到第600游戏刻时,存活时间为1游戏刻,系统先检查记忆过期,判定为没有过期,之后再将存活时间减1变为0游戏刻,在第601游戏刻此记忆才会被删除。在行为执行看来这个记忆存在了601游戏刻,而不是存活时间的600游戏刻。

启动与执行行为[编辑 | 编辑源代码]

对于所有行为,系统需要尝试启动它们,以便之后的执行。

由于活动中行为具有优先级,在启动或执行这些行为前需要对这些行为进行排序预处理。按照优先级,将所有活动中同一优先级的行为分组,之后将这些分组按照优先级排序放入一个优先级执行列表中。列表中的优先级从高到低排序,每个列表项都是活动和它对应优先级行为分组的映射。活动之间按照名称的小写形式的哈希码排序,一个活动中同一优先级的行为按照定义顺序排序。

尝试启动所有未启动的行为时,按照优先级从高到低,遍历列表项。每个列表项再遍历其中的活动,如果活动未被激活,则不计算对应的行为;否则,遍历活动对应优先级的行为,尝试启动所有当前没有运行的行为。

执行并尝试停止所有正在运行的行为时,按照优先级从高到低,遍历列表项。每个列表项再遍历其中的活动,但这里不检查活动是否被激活。遍历活动对应优先级的正在运行的行为,执行并尝试停止这些行为。

举例[编辑 | 编辑源代码]

下文以美西螈举例,说明记忆行为系统的执行流程。美西螈的生物AI在使用这套系统的生物中属于最简单的几种之一。

美西螈只会获得下列类型的记忆。换句话说,美西螈生物AI中这些记忆类型被注册:

记忆类型常量 记忆名称 备注
BREED_TARGET 繁殖对象 用于繁殖生物的另一个同类型生物,如果不存在繁殖就无法进行
NEAREST_LIVING_ENTITIES 周围生物 按距离由近到远排序
NEAREST_VISIBLE_LIVING_ENTITIES 周围可见生物 按距离由近到远排序
NEAREST_VISIBLE_PLAYER 周围可见玩家 按距离由近到远排序
NEAREST_VISIBLE_ATTACKABLE_PLAYER 周围可见且可以进行攻击的玩家 只存储最近的可攻击玩家
LOOK_TARGET 视角目标 可以绑定到实体,也可以绑定到方块位置
WALK_TARGET 行走目标 可以绑定到实体,也可以绑定到方块位置
CANT_REACH_WALK_TARGET_SINCE 无法到达行走目标计时 以游戏刻计
PATH 生物行走路径 由寻路系统动态计算,指定时间内更新一次
ATTACK_TARGET 攻击对象 用于近战攻击
ATTACK_COOLING_DOWN 攻击冷却 限制近战攻击的攻击频率
NEAREST_VISIBLE_ADULT 周围可见成年生物 用于跟随
HURT_BY_ENTITY 最近曾攻击自身的生物 判定装死
PLAY_DEAD_TICKS 装死计时 超出一定时间后结束装死
NEAREST_ATTACKABLE 最近可攻击生物 判定索敌,按距离由近到远排序
TEMPTING_PLAYER 正在使用物品吸引的玩家 只存储距离最近的玩家
TEMPTATION_COOLDOWN_TICKS 在进入求爱模式后的冷却 冷却过期时被删除
IS_TEMPTED 是否进入求爱模式
HAS_HUNTING_COOLDOWN 是否处于捕猎其他生物的冷却时间内 冷却过期时被删除
IS_PANICKING 是否处于惊慌状态

美西螈有5个感受器,按顺序执行。这些感受器用于检测周围的环境,并将这些数据写入到记忆中:

感受器 操作记忆 备注
检测周围生物
Nearest Living Entities
NEAREST_LIVING_ENTITIES
NEAREST_VISIBLE_LIVING_ENTITIES
检测成年生物
Nearest Adult
NEAREST_VISIBLE_ADULT 筛选NEAREST_VISIBLE_LIVING_ENTITIES记忆数据获得
检测伤害自身的生物
Hurt By
HURT_BY
HURT_BY_ENTITY
HURT_BY可以为任何实体,但在美西螈中没有用处;HURT_BY_ENTITY必须为生物
检测美西螈可攻击生物
Axolotl Attackables
NEAREST_ATTACKABLE 仅在HAS_HUNTING_COOLDOWN不存在时检测,筛选NEAREST_VISIBLE_LIVING_ENTITIES记忆数据获得
检测吸引美西螈的玩家
Axolotl Temptations
TEMPTING_PLAYER

美西螈一共有下列4个活动,活动中包含了一系列行为。其中核心活动就是核心活动CORE,默认活动是空闲活动IDLE

活动
优先级
核心活动
CORE
空闲活动
IDLE
战斗活动
FIGHT
装死活动
PLAY_DEAD
0 看向视角目标
Look At Target Sink
随机看向玩家
Set Entity Look Target Sometimes (Player)
停止攻击无效对象
Stop Attacking If Target Invalid
装死
Play Dead
1 走向行走目标
Move To Target Sink
繁殖
Animal Make Love (Axolotl)
更新超过范围的攻击对象行走目标
Set Walk Target From Attack Target If Target Out Of Reach
抹除记忆(装死计时)
Erase Memory If (PLAY_DEAD_TICKS)
2 退出装死状态
Validate Play Dead
门行为(按权重打乱,仅启动第一个)
Run One
近战攻击
Melee Attack
3 求爱模式冷却倒计时
Count Down Cooldown Ticks
开始攻击指定对象
Start Attacking
抹除记忆(攻击对象)
Erase Memory If (ATTACK_TARGET)
寻找水
Try Find Water
4 门行为(维持原顺序,尝试全部启动)
GateBehavior

其中,空闲活动优先级为2的门行为内部的子行为有:

行为 权重
跟随手持指定物品玩家
Follow Temptation
1
跟随成年美西螈
Baby Follow Adult
1

空闲活动优先级为4的门行为内部的子行为有:

行为 权重
随机游走(游泳)
Random Stroll (Swim)
2
随机游走(陆地)
Random Stroll (Stroll)
2
走向视角目标
Set Walk Target From Look Target
3
检查当前是否位于水和气泡柱
Trigger If (Is In Water Or Bubble)
5
检查当前是否在陆地
Trigger If (On Ground)
5

按照活动小写形式名称的哈希码,可以得出活动执行顺序是:核心活动、空闲活动、战斗活动、装死活动。

上表中所有行为的类型和记忆条件也在此给出:

行为 类型 要求存在记忆 要求不存在记忆
看向视角目标
Look At Target Sink
持续行为 LOOK_TARGET -
走向行走目标
Move To Target Sink
持续行为 WALK_TARGET PATH
退出装死状态
Validate Play Dead
单刻行为 PLAY_DEAD_TICKS -
求爱模式冷却倒计时
Count Down Cooldown Ticks
持续行为 TEMPTATION_COOLDOWN_TICKS -
随机看向玩家
Set Entity Look Target Sometimes (Player)
单刻行为 NEAREST_VISIBLE_LIVING_ENTITIES LOOK_TARGET
繁殖
Animal Make Love (Axolotl)
持续行为 NEAREST_VISIBLE_LIVING_ENTITIES
BREED_TARGET
IS_PANICKING
门行为(按权重打乱,仅启动第一个)
Run One
门行为 - -
跟随手持指定物品玩家
Follow Temptation
持续行为 TEMPTING_PLAYER TEMPTATION_COOLDOWN_TICKS
BREED_TARGET
IS_PANICKING
跟随成年美西螈
Baby Follow Adult
单刻行为 NEAREST_VISIBLE_ADULT WALK_TARGET
开始攻击指定对象
Start Attacking
单刻行为 - ATTACK_TARGET
寻找水
Try Find Water
单刻行为 - ATTACK_TARGET
WALK_TARGET
门行为(维持原顺序,尝试全部启动)
GateBehavior
门行为 - WALK_TARGET
随机游走(游泳)
Random Stroll (Swim)
单刻行为 - WALK_TARGET
随机游走(陆地)
Random Stroll (Stroll)
单刻行为 - WALK_TARGET
走向视角目标
Set Walk Target From Look Target
单刻行为 LOOK_TARGET WALK_TARGET
检查当前是否位于水和气泡柱
Trigger If (Is In Water Or Bubble)
单刻行为 - -
检查当前是否在陆地
Trigger If (On Ground)
单刻行为 - -
停止攻击无效对象
Stop Attacking If Target Invalid
单刻行为 ATTACK_TARGET -
更新超过范围的攻击对象行走目标
Set Walk Target From Attack Target If Target Out Of Reach
单刻行为 ATTACK_TARGET -
近战攻击
Melee Attack
单刻行为 ATTACK_TARGET
NEAREST_VISIBLE_LIVING_ENTITIES
ATTACK_COOLING_DOWN
抹除记忆(攻击对象)
Erase Memory If (ATTACK_TARGET)
单刻行为 ATTACK_TARGET -
装死
Play Dead
持续行为 HURT_BY_ENTITY PLAY_DEAD_TICKS
抹除记忆(装死计时)
Erase Memory If (PLAY_DEAD_TICKS)
单刻行为 PLAY_DEAD_TICKS -

根据上面的信息,我们可以开始分析美西螈的行为。

首先分析核心行为CORE。核心行为按照优先级只有4个行为:看向视角目标、走向行走目标、退出装死状态、求爱模式冷却倒计时。

  • 看向视角目标和走向行走目标是生物的基本行为,如果没有这两个行为生物就无法转向和走动,而这两个行为的本质是调用视角、移动、跳跃3个控制器。看向视角目标需要LOOK_TARGET记忆,由于它位于最高优先级,更低优先级的行为修改视角目标时生物需要等到下一游戏刻才可以转动视角。走向行走目标需要WALK_TARGET记忆,它处于优先级1,优先级0的行为修改行走目标时,生物可以立刻行走,但更低优先级的行为修改行走目标需要等到下一游戏刻才可以开始寻路和行走。
  • 退出装死状态是美西螈的必要行为,否则美西螈会一直保持装死状态无法恢复,具体实现在下文中提及。
  • 求爱模式冷却倒计时是保证生物不会连续地进入求爱模式,为繁殖留出冷却时间。这个行为只要保证TEMPTATION_COOLDOWN_TICKS存在它就不会停止,直到冷却时间已到记忆被抹除时自动停止。

如果美西螈没有攻击目标,也不处于装死状态,那么它就会激活空闲活动IDLE。空闲活动内有很多行为,用于控制美西螈在空闲状态下的随机活动,而不是让它在一个位置上不动。

  • 最高优先级的行为是随机看向玩家,与核心活动的看向视角目标行为处于同一个优先级,但是空闲行为晚于核心行为,所以随机看向玩家行为在设置LOOK_TARGET记忆后在下一游戏刻才会转动视角。
  • 下一个优先级的行为是繁殖,它要求生物周围必须有进入求爱模式的对应生物,且自身也必须进入求爱模式。因为繁殖行为要求不存在IS_PANICKING记忆,所以在惊慌状态下美西螈不会进行繁殖。在繁殖开始时,生物寻找最近的可繁殖的对应生物,并保存到记忆BREED_TARGET中。在繁殖过程中,记忆LOOK_TARGETWALK_TARGET会被持续设置为看向并走向对方,以防止其他行为影响繁殖行为。当繁殖行为停止时,这三个记忆会被一起抹除以保证其他行为可以正常运行。
  • 再下一优先级是一个门行为,只能启动其中一个行为。门行为内的两个子行为都负责跟随其他生物,所以这两个行为本身是冲突的,而门行为保证了这两个行为中只会启动其中一个避免冲突。
    • 当没有求爱模式冷却(TEMPTATION_COOLDOWN_TICKS),也不存在繁殖对象(BREED_TARGET,使得此行为与繁殖互斥),并且不处于惊慌状态(IS_PANICKING)时,美西螈才可能跟随一个手上拿着热带鱼桶的玩家。与大多数持续行为不同的是,这个行为不会超时,也就是说这个行为可以一直持续到不满足条件,而不会因为时间而自动停止,表现上来看就是美西螈可以一直跟随玩家而不是中途停止跟随。
    • 当周围有成年美西螈,而自身是幼年美西螈,且不存在行走目标(WALK_TARGET)时,美西螈可以跟随成年美西螈,并将行走目标定位到对应的成年美西螈。
  • 优先级3有两个行为,分别为开始攻击指定对象和寻找水,且攻击指定对象的执行顺序要早于寻找水。
    • 开始攻击指定对象的前提是当前没有攻击对象,附近有可攻击的对象,且美西螈现在没有在繁殖。当找到攻击对象后,攻击对象数据会被写入到记忆ATTACK_TARGET中。
    • 寻找水行为要求美西螈当前既没有攻击对象(ATTACK_TARGET)也没有行走目标(WALK_TARGET),也就是说如果美西螈正在繁殖、跟随玩家或成年美西螈、找到攻击对象时就不会主动寻找水维持自身湿润。寻找水也需要修改行走目标,所以寻找水行为和前文提及的几个行为互斥是为了防止美西螈移动错误。
  • 最低优先级是一个门行为,按顺序依次尝试启动所有行为。如果当前美西螈已经有了行走目标(WALK_TARGET),那么整个门行为都不会运行。这个门行为的作用就是保证美西螈在没有任何外界干扰下能自行随机走动。
    • 首先尝试启动的是游泳随机游走,使美西螈在水中可以随机移动。与意向系统的随机游走不同,记忆行为系统的任何随机游走类行为都无视无动作计数器,使得生物可以距离玩家很远的距离时可以随机游走。
    • 其次尝试启动的是陆地随机游走,使得美西螈可以在陆地上随机移动。此行为与上面的游泳随机游走互斥:如果游泳随机游走已经指定了行走目标(WALK_TARGET),那么陆地随机游走就不满足记忆条件,从而达到互斥。
    • 如果美西螈具有视角目标(LOOK_TARGET)记忆,看向的目标与自身所在位置的流体一致(都是空气或都是水),并且美西螈没有随机游走(即上文两种随机游走没有启动),那么美西螈可以移动向看向的目标,也就是让行走目标(WALK_TARGET)和视角目标一致,走向视角目标。
    • 剩下的两个行为对美西螈并没有什么作用,这两个行为只会检测状态,但不进行任何动作,也不修改任何记忆。

美西螈切换为战斗和装死活动有对应的条件,如果条件不满足则回到默认活动。如果美西螈正处于装死活动,则不会主动切换活动,直到核心活动中的退出装死状态行为使美西螈回到默认活动。尝试激活活动有对应的顺序:先尝试装死活动激活战斗活动,如果装死活动没有激活则尝试激活战斗活动,如果都无法激活则回到默认活动。

装死活动要求美西螈必须有装死计时记忆(PLAY_DEAD_TICKS),在美西螈受伤害时有概率获得这个记忆,过期时间为200游戏刻(10秒)。它只有2个行为:

  • 装死行为最长持续200游戏刻(10秒),且启动时必须有装死计时记忆(PLAY_DEAD_TICKS)和最近曾攻击自身生物的记忆(HURT_BY_ENTITY)。在启动时,美西螈的行走目标和视角目标记忆会被抹除,并给予自身200游戏刻(10秒)的生命恢复效果。如果在装死中途装死计时记忆被抹除或删除,则此行为也自动停止。
  • 另一个行为是抹除装死计时记忆。当美西螈有繁殖对象记忆(BREED_TARGET)时,美西螈自动抹除装死计时记忆(PLAY_DEAD_TICKS)。

由于装死活动的机制,有办法可以使得美西螈卡死在装死活动而使得美西螈无法移动和转动视角,步骤如下:

  1. 将两只美西螈A和B放入水中。
  2. 攻击其中一只美西螈A,直至装死。
    • 此时A进入装死活动。
  3. 同时给两只美西螈喂食热带鱼桶,使其繁殖。
    • 由于A进入装死活动,无法启动繁殖行为,但B可以启动繁殖行为,并可以发现A处于求爱模式。此时AB的繁殖对象记忆(BREED_TARGET)会由B的繁殖行为设置为对方。
  4. 繁殖结束,A完全陷入装死活动,但不启动装死行为,其他行为无法启动而冻结在原地。
    • A在装死活动中获得了来自对方设置的繁殖对象记忆(BREED_TARGET),这时抹除装死计时记忆行为满足条件而启动,抹除装死计时记忆(PLAY_DEAD_TICKS),使得装死行为条件不再满足而被停止。
    • 同时,从装死活动恢复到空闲活动的唯一方式(上文的退出装死状态行为,Validate Play Dead)也要求装死计时记忆(PLAY_DEAD_TICKS)存在,而现在此记忆已经不存在,那么美西螈就无法恢复到空闲活动,从而永远卡死在装死活动。
    • 装死活动中没有任何行为会设置行走目标和视角目标记忆,同时核心活动中也没有任何行为可以修改这两个记忆,使得美西螈被冻结。
  5. 重新加载区块可以使得美西螈恢复正常。
    • 活动本身不会被持久化到生物数据内,所以在重新加载后,生物会回到空闲活动,从而解除冻结状态。

战斗活动要求美西螈必须有攻击对象(ATTACK_TARGET)才可以被激活。按照优先级一共有4个行为:

  • 当美西螈的攻击对象已经濒死或死亡,或花了太长时间用于接近攻击对象但没有到达身边,那么这个攻击对象被认为无效,攻击对象记忆(ATTACK_TARGET)被抹除,在本游戏刻结束时战斗活动取消激活。如果玩家击杀了美西螈的攻击对象,那么美西螈会给予玩家状态效果。
  • 如果美西螈距离攻击对象超过自身近战攻击范围1格,则会更新行走目标绑定到攻击对象。当距离攻击对象很近时,将行走目标抹除,以防止在接近攻击对象时行走路径出现问题。
  • 当美西螈和攻击对象足够近时,美西螈就可以近战攻击。近战攻击具有冷却,即ATTACK_COOLING_DOWN记忆,在此记忆存在时不可以近战攻击,每次近战攻击后会产生20游戏刻(1秒)的此记忆。与意向系统的近战攻击不同,记忆行为系统的近战攻击就只有攻击这一个动作,不包含寻路动作,因为这些动作已经由前两个行为负责。
  • 与装死活动类似,当美西螈有繁殖对象记忆(BREED_TARGET)时,美西螈自动抹除攻击对象记忆(ATTACK_TARGET),使得玩家可以打断它们的捕猎而让它们去繁殖。与装死活动不同的是,战斗活动不会因为类似的方式而卡死,因为战斗活动可以通过多种方式回到空闲活动。

导航[编辑 | 编辑源代码]