Zh/Response System: Difference between revisions
Alanwong35 (talk | contribs) (→规则标准) |
No edit summary |
||
| (35 intermediate revisions by 7 users not shown) | |||
| Line 1: | Line 1: | ||
{{ | {{LanguageBar|title = 响应系统}} | ||
The '''Response System'''(响应系统)用于决定 NPC(或玩家)在想要说什么或是否说什么时应该使用哪种语言(和/或动画)。 | The '''Response System'''(响应系统)用于决定 NPC(或玩家)在想要说什么或是否说什么时应该使用哪种语言(和/或动画)。 | ||
{{ | {{note|本文大部分内容基于 Source 2013 分支。{{l4d|4}} 使用了一个重写的响应系统,它执行大部分相同的功能,但具有不同的优化、路径和实用程序,本文尚未完整记录。此增强系统也适用于求生之路之后发布的所有游戏,包括 {{l4d2|4}}。该系统的代码在{{L|Authoring Tools/SDK (Alien Swarm)|异形丛生(Alien Swarm)的创作工具}}中公开可用。}} | ||
{{toc-right}} | {{toc-right}} | ||
| Line 13: | Line 11: | ||
例如,当玩家杀死敌方 NPC 时,HL2 情节系列中的{{ent|npc_alyx}}会说出<code>TLK_PLAYER_KILLED_NPC</code>概念。这个概念对于与 NPC 相关的条件或它被杀死的方式有额外的标准。如果玩家通过爆头杀死了 NPC,则响应系统将选择需要该标准的响应,这通常会导致艾利克斯称赞玩家的射击或评价这是爆头。 | 例如,当玩家杀死敌方 NPC 时,HL2 情节系列中的{{ent|npc_alyx}}会说出<code>TLK_PLAYER_KILLED_NPC</code>概念。这个概念对于与 NPC 相关的条件或它被杀死的方式有额外的标准。如果玩家通过爆头杀死了 NPC,则响应系统将选择需要该标准的响应,这通常会导致艾利克斯称赞玩家的射击或评价这是爆头。 | ||
响应系统通常使用<code>scripts/talker</code>目录中的脚本。当它接收到一个概念及其标准时,它会在响应脚本中搜索与其概念和标准相匹配的'''规则'''(rules)。当它找到一个时,它会使用该规则的'''响应'''(response)或响应选择。响应可以是 | 响应系统通常使用<code>scripts/talker</code>目录中的脚本。当它接收到一个概念及其标准时,它会在响应脚本中搜索与其概念和标准相匹配的'''规则'''(rules)。当它找到一个时,它会使用该规则的'''响应'''(response)或响应选择。响应可以是{{L|Soundscripts|声音脚本}}、{{L|Sentences|句子}},甚至是实例化的{{L|Choreography Implementation|排编场景}}。 | ||
尽管有这些优点,但大多数 NPC 默认不使用此系统。例如,{{ent|npc_pigeon}}默认只使用声音脚本,不使用响应系统。 | 尽管有这些优点,但大多数 NPC 默认不使用此系统。例如,{{ent|npc_pigeon}}默认只使用声音脚本,不使用响应系统。 | ||
以下是使用响应系统的地方的快速列表: | 以下是使用响应系统的地方的快速列表: | ||
* 在 {{hl2|4 | * 在 {{hl2|4}} 中,大多数玩家同伴 NPC({{L|npc_citizen|公民}}、{{L|npc_alyx|艾利克斯}}等)使用 NPC 语音响应系统。 | ||
* 在 {{tf2|4 | * 在 {{tf2|4}} 中,所有兵种(all classes)都使用响应系统来进行语音命令和嘲讽响应。 | ||
* 在 {{l4ds|4 | * 在 {{l4ds|4}} 中,所有幸存者都使用响应系统来响应玩家在世界上的行为和事件。 | ||
* 在 {{portal2|4 | * 在 {{portal2|4}} 中,Atlas 和 P-body(合作模式下的机器人)都使用响应系统来进行嘲讽手势。 | ||
* 在 {{csgo|4 | * 在 {{csgo|4}} 中,所有玩家角色都使用响应系统并跟踪已使用的响应。 | ||
* 在 {{hla|4 | * 在 {{hla|4}} 中,参见 {{L|HLALYX:Response_rules.txt}}。 | ||
{{ | {{ModernCodenote|响应系统通常用于从具有<code>CAI_ExpresserHost<></code>模板类的<code>CBaseFlex</code>派生的类上,该模板类在<code>CAI_BaseActor</code>上自动实现。所有 NPC 和玩家都已从<code>CBaseFlex</code>派生,因此你通常只想使用<code>CAI_ExpresserHost<></code>,但响应系统可以使用<code>DispatchResponse()</code>函数以更有限的方式在任何实体上使用,这就是{{ent|env_speaker}}的工作方式。<code>GetResponseSystem()</code>可用于使概念搜索特定的响应系统树,如果你计划在没有<code>CAI_ExpresserHost<></code>的情况下使用<code>DispatchResponse()</code>,则必须将其覆盖。}} | ||
== 目的 == | == 目的 == | ||
| Line 33: | Line 31: | ||
这是一个来自 NPC 使用响应系统的复杂对话树的示例: | 这是一个来自 NPC 使用响应系统的复杂对话树的示例: | ||
*''I just killed an enemy. 我刚刚杀死了一个敌人。'' | *''I just killed an enemy. 我刚刚杀死了一个敌人。'' | ||
:*''Did I use a shotgun? | :*''Did I use a shotgun? 我用了霰弹枪吗?'' | ||
::*"Eat shotgun! | ::*"Eat shotgun! 吃霰弹枪!" | ||
:*''Was the enemy really close? 敌人真的很近吗?'' | :*''Was the enemy really close? 敌人真的很近吗?'' | ||
::*"You got too close! 你离的太近了!" | ::*"You got too close! 你离的太近了!" | ||
| Line 49: | Line 47: | ||
== 构成 == | == 构成 == | ||
{{ | {{note|'Criterion' 是 'Criteria'(标准)的单数形式。}} | ||
响应系统由四个核心部分组成:'''Concepts'''(概念), '''Criteria'''(标准), '''Rules'''(规则),和 '''Response Groups'''(响应组)。它们的使用方法如下: | 响应系统由四个核心部分组成:'''Concepts'''(概念), '''Criteria'''(标准), '''Rules'''(规则),和 '''Response Groups'''(响应组)。它们的使用方法如下: | ||
| Line 68: | Line 66: | ||
=== 概念 === | === 概念 === | ||
'''concept'''(概念) 是一个 | '''concept'''(概念) 是一个{{L|string|字符串}} ,它表示角色语音尝试的高级原因。 代码中定义了一组概念,这些概念将被自动调用,但从技术上讲,概念只是字符跟踪的特殊高级标准。它们与任何东西无关,你可以在响应文件中自由创建你自己的。你可以在代码中或使用参与者的<code>DispatchResponse</code>或<code>{{L|SpeakResponseConcept}}</code>输入来调用概念。 | ||
以下是半条命 2 中使用的一些预定义 NPC 概念的列表: | 以下是半条命 2 中使用的一些预定义 NPC 概念的列表: | ||
| Line 82: | Line 80: | ||
TLK_PLYR_PHYSATK 当我被玩家扔过来的物体砸中了。 | TLK_PLYR_PHYSATK 当我被玩家扔过来的物体砸中了。 | ||
不是所有的 NPC 都会说所有的概念,也不是所有的 NPC 在相同的情况下都会说概念。有关完整列表,请参阅 | 不是所有的 NPC 都会说所有的概念,也不是所有的 NPC 在相同的情况下都会说概念。有关完整列表,请参阅{{L|list of predefined response concepts|响应概念列表}}。 | ||
=== 标准集(Criteria Set) === | === 标准集(Criteria Set) === | ||
''' | '''标准(Criteria)'''是一组条件,其中包含与对话者的当前状态相关的数据,以及每当请求尝试进行对话时概念的情况。它可以被解释为一组 {{L|KeyValues class|键值}}。以下是一个由{{ent|npc_alyx}}创建的标准集的例子,她试图说话因为她刚刚杀死了当前的敌人: | ||
concept = TLK_ENEMY_DEAD NPC 尝试说话的概念。 | concept = TLK_ENEMY_DEAD NPC 尝试说话的概念。 | ||
map = d3_c17_07 当前地图的名称。 | map = d3_c17_07 当前地图的名称。 | ||
classname = npc_alyx 正在说话的NPC的 | classname = npc_alyx 正在说话的NPC的{{L|classname}}。 | ||
name = alyx 正在说话的NPC的 | name = alyx 正在说话的NPC的{{L|targetname}}。 | ||
health = 75 正在说话的NPC的生命值。 | health = 75 正在说话的NPC的生命值。 | ||
healthfrac = 0.9375 正在说话的NPC的生命值与它最大生命值的比值(默认 npc_alyx 的最大生命值是80)。 | healthfrac = 0.9375 正在说话的NPC的生命值与它最大生命值的比值(默认 npc_alyx 的最大生命值是80)。 | ||
| Line 97: | Line 95: | ||
activity = ACT_RUN 正在说话的NPC正在执行的动画活动。 | activity = ACT_RUN 正在说话的NPC正在执行的动画活动。 | ||
npcstate = [NPCState::Combat] 正在说话的NPC的 AI 状态。 | npcstate = [NPCState::Combat] 正在说话的NPC的 AI 状态。 | ||
enemy = npc_combine_s 正在说话的NPC的当前敌人的 | enemy = npc_combine_s 正在说话的NPC的当前敌人的{{L|classname}}。 | ||
speed = 79.235 正在说话的NPC的移动速度。 | speed = 79.235 正在说话的NPC的移动速度。 | ||
weapon = weapon_alyxgun 正在说话的NPC握着的武器。 | weapon = weapon_alyxgun 正在说话的NPC握着的武器。 | ||
| Line 103: | Line 101: | ||
seeplayer = 1 正在说话的NPC能否看见玩家。 | seeplayer = 1 正在说话的NPC能否看见玩家。 | ||
seenbyplayer = 0 正在说话的NPC是否在玩家的视野内。 | seenbyplayer = 0 正在说话的NPC是否在玩家的视野内。 | ||
readiness = agitated 正在说话的NPC的 | readiness = agitated 正在说话的NPC的{{L|readiness}}级别。 | ||
playerhealth = 100 玩家目前生命值。 | playerhealth = 100 玩家目前生命值。 | ||
playerhealthfrac = 1.000 玩家目前生命值的生命值与它最大生命值的比值。 | playerhealthfrac = 1.000 玩家目前生命值的生命值与它最大生命值的比值。 | ||
| Line 121: | Line 119: | ||
=== 规则标准 === | === 规则标准 === | ||
根据规则是有一个标准列表的,这些标准会根据人物的标准集进行测试。当规则得到分数(point)时,会根据给定数据检查每个标准,并且该规则会收到成功匹配的标准的'''分数(point)'''。用于规则的标准获得分数由标准的'''权重'''决定。 | |||
标准在脚本文档中的定义格式(见下文): | 标准在脚本文档中的定义格式(见下文): | ||
| Line 136: | Line 134: | ||
:*Inverse Numeric values: "!=0" (如果值不等于 0 则匹配) | :*Inverse Numeric values: "!=0" (如果值不等于 0 则匹配) | ||
:*String value: "npc_alyx", "weapon_alyxgun", or "npc_combine_s". | :*String value: "npc_alyx", "weapon_alyxgun", or "npc_combine_s". | ||
:* | :*{{L|Enumeration|Enumerated}} value: "[NPCState::Combat]". | ||
:* | :*范围(Ranges): | ||
:**">0" : 如果值大于 0,则匹配 | :**">0" : 如果值大于 0,则匹配 | ||
:**"<=0.5" : 如果值小于或等于 0.5,则匹配 | :**"<=0.5" : 如果值小于或等于 0.5,则匹配 | ||
:**">10,<=50" : 如果值大于 10 且小于或等于 50,则匹配 | :**">10,<=50" : 如果值大于 10 且小于或等于 50,则匹配 | ||
:**">0,<[NPCState::Alert] : 如果值大于 0 且小于 NPCState::Alert 的枚举值,则匹配。 | :**">0,<[NPCState::Alert] : 如果值大于 0 且小于 NPCState::Alert 的枚举值,则匹配。 | ||
:{{ | :{{note|这默认不支持通配符。}} | ||
;weight X | ;weight X | ||
: 这是一个可选参数,其中 X | : 这是一个可选参数,其中 X 是该标准在匹配时值所得的分数(point)。如果未指定,则标准默认为 1 point。 | ||
;required | ;required | ||
: 这是一个可选参数,要想使用rules | : 这是一个可选参数,要想使用rules containing,则得需要此标准。如果所需标准未成功匹配,则包含它的规则所得分数会为0并立即跳过。大多数标准都使用此参数。 | ||
关于半条命2的一些实例: | |||
*下面的例子中定义了一个名为'''PlayerNear'''的标准 ( | *下面的例子中定义了一个名为'''PlayerNear'''的标准 (这是用于检查与确保玩家在以对话NPC以中心500格的范围内) | ||
:<pre>criterion "PlayerNear" "distancetoplayer" "<500" required</pre> | :<pre>criterion "PlayerNear" "distancetoplayer" "<500" required</pre> | ||
*下面的例子中则定义了一个名为'''IsCitizen'''的标准 (这是用于检查与确保说话的NPC是{{ent|npc_citizen}}) | *下面的例子中则定义了一个名为'''IsCitizen'''的标准 (这是用于检查与确保说话的NPC是{{ent|npc_citizen}}) | ||
| Line 158: | Line 156: | ||
:<pre>criterion "IsBob" "targetname" "bob" required</pre> | :<pre>criterion "IsBob" "targetname" "bob" required</pre> | ||
{{ | {{tip|概念(concept)是一个标准,其权重几乎总是 5}} | ||
=== | === 规则 === | ||
一个'''规则''' (Rule) 包括标准列表和至少一个响应组。该规则为成功匹配演讲者的标准集的每个标准接收分数。得分最高的规则将指向其中一个响应组,该响应组用于确定NPC将使用的确切语音。规则是在脚本文件中定义的(见下文)。使用以下格式: | |||
<pre> | <pre> | ||
rule <rule name> | rule <rule name> | ||
| Line 172: | Line 169: | ||
} | } | ||
</pre> | </pre> | ||
参数如下: | |||
*'''rule name''' : | *'''rule name''' : 规则的名称。不得与现有规则匹配。 | ||
*'''criteria''' : | *'''criteria''' : 规则应根据的标准集进行评分。 | ||
*'''response''' : | *'''response''' : 如果此规则得分最高,则应选择的响应组列表。 | ||
*'''matchonce''' : | *'''matchonce''' : 一个可选参数,如果指定了该参数,则一旦选择该规则一次,该参数将导致该规则被停用。 | ||
*'''applyContext''' : | *'''applyContext''' : 应用响应上下文的可选参数。有关详细信息,请参阅[[#响应上下文]]。 | ||
例如,以下文本定义了一个名为 ''CitizenTalkStare'' 的规则。''ConceptTalkStare'' 是一个检查说话的 NPC 想说的'''概念'''是否为“TLK_STARE”的标准。''IsCitizen'' 是一个检查说话的 NPC 是否是{{L|npc_citizen|公民}}的标准。''NPCIdle'' 是一个检查以确保 NPC 的状态为“NPCState::Idle”的标准。如果此规则得分最高,则将使用的响应组为 ''CitizenTalkStare''。 | |||
<pre> | <pre> | ||
rule CitizenTalkStare | rule CitizenTalkStare | ||
| Line 187: | Line 184: | ||
} | } | ||
</pre> | </pre> | ||
请注意,规则名称和响应组名称可以是相同的,因为规则名称只需要在规则之间唯一,而响应组名称只需在组之间唯一。 | |||
=== | === 响应组 === | ||
一个'''响应组'''包含一组可能的'''响应''',以及一些可选的数据,用于定义如何使用这些响应。当规则选择了一个响应组时,从列表中选择一个响应并交给发言者使用。 | |||
响应组是在脚本文件内定义的(见下文)。使用以下格式: | |||
<pre> | <pre> | ||
response <response name> | response <response name> | ||
| Line 204: | Line 202: | ||
} | } | ||
</pre> | </pre> | ||
响应组的参数如下: | |||
*'''permitrepeats''' | * '''permitrepeats''':如果指定,该组中的响应可以重复。如果未指定,默认行为是在重复任何响应之前使用列表中的所有响应。 | ||
*'''sequential''' | * '''sequential''':如果指定,将按照在组中列出的顺序使用响应。如果未指定,默认行为是从列表中随机选择响应。 | ||
*'''norepeat''' | * '''norepeat''':如果指定,一旦播放了列表中的所有响应,响应组将被禁用。选择该响应组的任何规则都将对发言者返回无响应。 | ||
==== 响应 ==== | ==== 响应 ==== | ||
| Line 213: | Line 211: | ||
'''响应'''是由系统选择然后由说话者使用的实际响应。响应组可以根据需要列出尽可能多的响应,每个响应都应该以下类型中的一个: | '''响应'''是由系统选择然后由说话者使用的实际响应。响应组可以根据需要列出尽可能多的响应,每个响应都应该以下类型中的一个: | ||
*'''speak''' : 该响应是一个 | *'''speak''' : 该响应是一个{{L|Soundscripts|音效脚本}}或原始音频文件。 | ||
*'''sentence''' : 该响应是{{ent|sentences.txt}}中的一段句子 | *'''sentence''' : 该响应是{{ent|sentences.txt}}中的一段句子 | ||
*'''scene''' : 该响应是一个<code>.vcd</code>文件。详见 | *'''scene''' : 该响应是一个<code>.vcd</code>文件。详见{{L|Choreography Implementation|场景编排的实现}}。 | ||
*'''response''' : The response is a reference to another response group which should be selected instead. | *'''response''' : The response is a reference to another response group which should be selected instead. | ||
*'''print''' : 该响应是一段在<code>developer 1</code>模式下位于说话者位置生成的占位用响应。{{ | *'''print''' : 该响应是一段在<code>developer 1</code>模式下位于说话者位置生成的占位用响应。{{note|{{mapbase|1}}默认将其替换为类似于{{ent|game_text}}的屏幕信息}} | ||
*'''entityio''' {{since | *'''entityio''' {{since|{{l4d}}}}{{confirm}} : 该响应是一个{{L|Inputs and Outputs|I/O事件}} ,它以说话者作为触发者(activator)对特定的实体触发IO事件,格式为<code>entityio "<name> <input> <param>"</code>。这与Followup Responses不一样,后者将会在下文进行介绍 | ||
==== | ==== 响应后延迟参数 ==== | ||
每个响应都支持各种可选参数。 | |||
* '''nodelay''':在响应完成后,允许发言者立即再次发言。 | |||
* '''defaultdelay''':在响应完成后,发言者将在2.8到3.2秒之间的随机时间内不被允许发言。 | |||
* '''delay X''':在响应完成后,发言者将在X秒内不被允许发言。X也可以是一个范围,例如"5.5,7.5"。 | |||
*'''weapondelay X''' | * '''weapondelay X''':当响应开始时,发言者将在X秒内不能开火武器。默认仅在HL2 NPC盟友上可用。 | ||
*'''speakonce''' | * '''speakonce''':防止重复使用响应。 | ||
*'''odds X''' | * '''odds X''':如果指定,选择此响应时,发言者有可能保持沉默而不是说出响应。odds 是取消响应的机会(0-100%),例如25表示不说话的几率为25%。 | ||
*'''respeakdelay''' | * '''respeakdelay''':如果指定,除非概念在至少X秒内没有被说过,否则不能使用此响应。X也可以是一个范围,例如"5.5,7.5"。 | ||
*'''soundlevel''' | * '''soundlevel''':如果指定,应该在响应中使用该声音级别,而不是默认的SNDLVL_TALKING。 | ||
*'''displayfirst''' | * '''displayfirst''':如果指定,应首先使用此响应(忽略权重参数)。 | ||
*'''displaylast''' | * '''displaylast''':如果指定,应最后使用此响应(忽略权重参数)。 | ||
*'''weight''' | * '''weight''':如果指定,用于加权选择列表中的响应。默认情况下,所有响应的权重均为1。请注意,响应在选择了所有其他响应之前不会重复,这意味着一旦选择了所有高权重的响应,系统将只计算权重较低的响应。可以通过'''permitrepeats'''来抵消这一点。 | ||
*'''noscene''' | * '''noscene''':阻止响应系统为'''speak'''响应创建自动生成的场景。 | ||
*'''stop_on_nonidle''' | * '''stop_on_nonidle''':当响应被说出时,当NPC进入非空闲状态时停止场景。在Source 2013中,仅在HL2剧集模组中的'''scene'''响应上起作用。 | ||
*'''predelay''' | * '''predelay''':当选择响应时,直到过了X秒才会实际说出来。仅在'''scene'''响应上起作用。X也可以是一个范围,例如"5.5,7.5"。 | ||
例如,下面的响应组由{{L|npc_citizen|市民}}用于回应TLK_STARE概念。市民将按照它们在列表中的顺序使用响应(由于 ''sequential'' 参数)。每个被选择的响应都会停止NPC发言一段随机时间,介于10到20秒之间。 | |||
<pre> | <pre> | ||
response "CitizenTalkStare" | response "CitizenTalkStare" | ||
| Line 250: | Line 248: | ||
</pre> | </pre> | ||
== | == 脚本文件 == | ||
{{Code|/scripts/talker/response_rules.txt}} 是基本脚本文件,包含响应规则系统使用的所有条件、规则和响应组。该文件还可以包括使用 '''#include''' 关键字的其他文件,这允许你根据 NPC、地图等干净地划分规则。请注意,一些实体,如 {{ent|env_speaker}},指定了自己的脚本文件,其中包含实体要使用的条件、规则和响应组的子集。有关火车站终端公告使用的示例,请参见 {{Code|scripts/talker/terminal_pa.txt}}。 | |||
== | == 响应上下文 == | ||
响应上下文类似于地图作者设置的标准。它们通过“Response Contexts”(<code>ResponseContext</code>)键值或<code>AddContext</code>输入进行设置,格式如下:<code>key:value;key:value;key:value;</code>……其中key是“键”,value是“值”。 | |||
{{todo|关于响应上下文的独特部分,还有更多关于响应上下文需要解释的内容!}} | |||
{{ | == 后续响应 == | ||
{{l4d|4}}引入了“后续响应”,即在响应后发生的事件。它们被触发为响应参数,类似于'''odds'''、'''predelay'''等。{{codenote|后续系统的代码可在{{L|Authoring Tools/SDK (Alien Swarm)|Alien Swarm SDK}}中找到,以及重新编写的响应系统的其余部分。}} | |||
* '''fire''':通过I/O系统使用发言者作为激活器和调用者触发一个输入。格式为<code>fire <target> <input> <delay></code>。不支持参数。 | |||
* '''then''':导致在实体上分派另一个响应。格式为<code>then <target> <concept> <response contexts> <delay></code>。用于使角色动态地相互响应。 | |||
{{note|负延迟会导致后续在发言者“开始”说话后X秒被分派,而不是在他们说完时。}} | |||
可以使用一些独特的目标名称: | |||
* '''self''':发言响应的实体。 | |||
* '''subject''':使用发言者“'''Subject'''”上下文中找到的实体名称(如果存在)。游戏为{{ent|info_remarkable}}响应设置了这个。 | |||
* '''from''':使用发言者“'''From'''”上下文中找到的实体名称(如果存在)。游戏将其设置为上一个后续响应者的名称,允许后续响应来回弹跳。 | |||
* '''any''':分派到<code>rr_followup_maxdist</code>(默认为1800)中存储的任何有效响应者。 | |||
* '''all''':分派到<code>rr_followup_maxdist</code>(默认为1800)中存储的''所有''有效响应者。 | |||
{{note|“Subject”和“From”上下文仅存储实体名称,因此当存在具有相同名称的多个潜在目标时要小心!}} | |||
来自Left 4 Dead 2中的示例<code>coach.txt</code>: | |||
<pre> | <pre> | ||
| Line 288: | Line 284: | ||
</pre> | </pre> | ||
== | == 高级响应规则的使用 == | ||
响应系统可以以许多高级和专业的方式使用。以下是一些用于系统高级用途的技巧和窍门: | |||
;使用<code>DispatchResponse</code>触发自定义响应 | |||
:实际上,任何可以在脚本文件中找到的响应概念都可以传递给NPC,只要它不限于AI预定义的TLK_*概念。 | |||
:''例如'',您可能希望在玩家成功解决谜题的一部分时,旁观组中的NPC发表祝贺的响应概念。 | |||
:HL2中的玩家盟友还具有更高级处理和条件的<code>SpeakResponseConcept</code>输入。 | |||
查看EP1/EP2中Alyx的响应脚本或L4D幸存者的响应脚本,以获取更多高级响应系统使用示例。 | |||
== | == 调试 == | ||
{{todo|{{L|sv_debugresponses}}}} | |||
== | == 注意 == | ||
* | * 要能够使用响应系统,必须使用由 {{L|CAI_BaseActor}} 类派生的 NPC。 | ||
* | * 参见<code>scripts/talker/npc_*.txt</code>文件以获取特定 NPC 响应规则的示例。 | ||
* | * <code>scripts/talker/response_rules.txt</code>是响应规则系统的列表。如果为新 NPC 添加新的响应规则脚本文件,请确保在<code>scripts/talker/response_rules.txt</code>文件的末尾通过 #include 语句包括该文件。 | ||
* | == 另请参阅 == | ||
* | (译注:以下链接链接到英文页面) | ||
* {{L|Concept|概念}} | |||
* {{L|Criterion|标准}} | |||
* {{L|Context|上下文}} | |||
* {{L|Rule|规则}} | |||
* {{L|Response|响应}} | |||
== | == 外部链接 == | ||
* [https://www.gdcvault.com/play/1015528/AI-driven-Dynamic-Dialog-through Elan Ruskin | * [https://www.gdcvault.com/play/1015528/AI-driven-Dynamic-Dialog-through Elan Ruskin 在 GDC 2012 上的“用于上下文对话和游戏逻辑的规则数据库”演示文稿],它描述了响应系统及其演变。 (幻灯片:[https://cdn.akamai.steamstatic.com/apps/valve/2012/GDC2012_Ruskin_Elan_DynamicDialog.pdf]) | ||
* [https://www.youtube.com/watch?v=j4eIu6LxdZg Two Bots One Wrench: Environmentally Responsive Speech Video], | * [https://www.youtube.com/watch?v=j4eIu6LxdZg Two Bots One Wrench: Environmentally Responsive Speech Video], 演示视频 #1 | ||
* [https://www.youtube.com/watch?v=2aozwfumnH4 Two Bots One Wrench: Memory And Context], | * [https://www.youtube.com/watch?v=2aozwfumnH4 Two Bots One Wrench: Memory And Context], 演示视频 #2 | ||
* [https://www.youtube.com/watch?v=pYpCeql993M Two Bots One Wrench: Conversation], | * [https://www.youtube.com/watch?v=pYpCeql993M Two Bots One Wrench: Conversation], 演示视频 #3 | ||
[[Category:AI Programming | [[Category:AI Programming]] | ||
{{ACategory|AI Programming}} | |||
Latest revision as of 23:44, 24 September 2025
The Response System(响应系统)用于决定 NPC(或玩家)在想要说什么或是否说什么时应该使用哪种语言(和/或动画)。
大多数响应系统用户都是为了响应游戏中发生的事件而发言。语音可以从代码或地图的输入中触发。触发语音涉及响应概念,它对应于系统中的响应。概念是用于特定事件的语音类别,例如注意到危险 (TLK_DANGER) 或看到敌人 (TLK_STARTCOMBAT)。虽然一个概念可以单独用于基本和简单的对话,但语音也可以通过各种标准来触发,这些标准描述了与该概念和/或说话者的当前状态和周围世界相关的事物。这允许复杂的对话树涉及不同情况下的不同台词。
例如,当玩家杀死敌方 NPC 时,HL2 情节系列中的npc_alyx会说出TLK_PLAYER_KILLED_NPC概念。这个概念对于与 NPC 相关的条件或它被杀死的方式有额外的标准。如果玩家通过爆头杀死了 NPC,则响应系统将选择需要该标准的响应,这通常会导致艾利克斯称赞玩家的射击或评价这是爆头。
响应系统通常使用scripts/talker目录中的脚本。当它接收到一个概念及其标准时,它会在响应脚本中搜索与其概念和标准相匹配的规则(rules)。当它找到一个时,它会使用该规则的响应(response)或响应选择。响应可以是声音脚本、句子,甚至是实例化的排编场景。
尽管有这些优点,但大多数 NPC 默认不使用此系统。例如,npc_pigeon默认只使用声音脚本,不使用响应系统。
以下是使用响应系统的地方的快速列表:
- 在
半衰期2 中,大多数玩家同伴 NPC(公民、艾利克斯等)使用 NPC 语音响应系统。 - 在
军团要塞2 中,所有兵种(all classes)都使用响应系统来进行语音命令和嘲讽响应。 - 在

求生之路系列 中,所有幸存者都使用响应系统来响应玩家在世界上的行为和事件。 - 在
传送门2 中,Atlas 和 P-body(合作模式下的机器人)都使用响应系统来进行嘲讽手势。 - 在
反恐精英:全球攻势 中,所有玩家角色都使用响应系统并跟踪已使用的响应。 - 在
半衰期:爱莉克斯 中,参见 HLALYX:Response_rules.txt。
CAI_ExpresserHost<>模板类的CBaseFlex派生的类上,该模板类在CAI_BaseActor上自动实现。所有 NPC 和玩家都已从CBaseFlex派生,因此你通常只想使用CAI_ExpresserHost<>,但响应系统可以使用DispatchResponse()函数以更有限的方式在任何实体上使用,这就是env_speaker的工作方式。GetResponseSystem()可用于使概念搜索特定的响应系统树,如果你计划在没有CAI_ExpresserHost<>的情况下使用DispatchResponse(),则必须将其覆盖。目的
创建响应系统,以便 NPC、玩家等使用统一且强大的系统来管理语音。它不仅允许开发人员和作家创建复杂的对话树,而且还允许模组制作者轻松修改或向游戏添加新语音,而无需编写代码或修改 BSP 文件,同时仍然可以完全控制语音的方式和使用次数。
该系统最适合用于来自 AI 系统的语音,因为这些台词将在整个游戏中被多次说出。 (例如,市民在装填武器时会说些什么。很多市民会在游戏过程中装填武器。)
这是一个来自 NPC 使用响应系统的复杂对话树的示例:
- I just killed an enemy. 我刚刚杀死了一个敌人。
- Did I use a shotgun? 我用了霰弹枪吗?
- "Eat shotgun! 吃霰弹枪!"
- Was the enemy really close? 敌人真的很近吗?
- "You got too close! 你离的太近了!"
- "Thanks for getting close! 感谢你靠近!"
- Was the enemy a npc_headcrab? 敌人是 npc_headcrab 吗?
- "You're not getting MY head! 你没有得到我的头!"
- "I hate headcrabs! 我恨猎头蟹!"
你还可以使用标准组合。
- Did I use a shotgun against a npc_headcrab really close to me? 我用霰弹枪对付离我很近的 npc_headcrab 吗?
- "You got too close to my shotgun, headcrab! 你离我的霰弹枪太近了,猎头蟹!"
你还可以控制单独的行,使其在一定时间内不重复,或者根本不重复。
构成
响应系统由四个核心部分组成:Concepts(概念), Criteria(标准), Rules(规则),和 Response Groups(响应组)。它们的使用方法如下:
- 一个 NPC 为一个语音概念(Concept)请求一行语音。
- 例如,假设我们的 NPC 为
TLK_SHOT概念请求一行语音。 NPC 被敌人击中时会说出这个概念。
- 例如,假设我们的 NPC 为
- NPC 收集了一堆反映 NPC 当前状态的标准(Criteria)以及有关世界状态的其他相关数据。许多概念也有修饰符(Modifier),这是特定概念特有的标准,通常反映事件本身。
- 当 NPC 为
TLK_SHOT概念请求一行时,游戏会将 NPC 当前的健康状况等作为默认标准集的一部分进行组合。然后,它附加了概念的修饰符,其中可能包括射击他们的敌人的类型、他们受到的伤害量等。
- 当 NPC 为
- 概念和标准 被传递到 NPC 的响应系统中,该系统通常是所有 NPC 共享的单个全局实例。
- 响应系统搜索其规则(Rules)的大列表。
- 每个规则都包含一个标准列表,该列表根据 NPC 预先设置的标准进行测试。请注意,概念在此阶段被视为高优先级标准。
- 每个规则都会根据有多少标准是正确的而获得一个分数。如果至少一个标准被标记为“必需”(required)并且不满足,则永远不会选择该规则。大多数标准都设置为必需,但不需要的标准只会提高规则的分数。
- 在我们的
TLK_SHOT示例中,可能有多个包含不同行的TLK_SHOT规则。一条规则可能包含测试“NPC 是否离射击他的敌人非常近”的标准。另一个规则可能会测试是否是特定类型的敌人向他开枪(例如联合军士兵)。另一个规则可能会测试 NPC 是否在射击后剩余的生命值低于 25%。
- 在我们的
- 响应系统对其列表中的所有规则进行评分,并选择得分最高的一项。得分最高的规则指定一个响应组(Response Group)。
- 响应组只是可能的响应列表,每个响应可能是一行语音和/或动画。一个响应根据响应组和个人响应的设置选择。选择有效响应后,NPC将执行该响应。
- 在我们的
TLK_SHOT示例中,假设选择了<25% 健康规则。该规则将有一个响应组,其中可能包含一系列行,例如“One more shot like that, and I'm done for! 再打一枪,我就完蛋了!”、“Oh man, I'm in trouble! 哦,伙计,我有麻烦了!”或“I need medical attention over here! 我需要医疗照顾!” TLK_SHOT的另一条规则可以检查射击他们的敌人是否是联合军士兵,并指向一个响应组,其中包含“That Combine soldier's got me pinned down! 那个联合军士兵让我被压制了!”或“Help me with this soldier! 帮我对付这个士兵!”。另一个规则可以检查敌人是否是联合武装直升机,并用“That gunship is kicking my butt! 那艘武装直升机在踢我的屁股!”和“Someone help me take down that gunship before it kills me! 有人帮我在它杀了我之前拿下那艘武装直升机!”指向一个组。
- 在我们的
- 如果没有任何规则符合给定的标准[或者所选的反应组没有重复并且已经筋疲力尽(exhausted)],NPC不会说任何话。
概念
concept(概念) 是一个字符串 ,它表示角色语音尝试的高级原因。 代码中定义了一组概念,这些概念将被自动调用,但从技术上讲,概念只是字符跟踪的特殊高级标准。它们与任何东西无关,你可以在响应文件中自由创建你自己的。你可以在代码中或使用参与者的DispatchResponse或SpeakResponseConcept输入来调用概念。
以下是半条命 2 中使用的一些预定义 NPC 概念的列表:
TLK_HELLO 当我第一次遇见玩家。 TLK_IDLE 当我被闲置了一段时间。 TLK_USE 当玩家尝试使用(+use)我。 TLK_PLPUSH 当玩家把我推开。 TLK_STARE 当玩家盯了我一会儿。 TLK_DANGER 当我察觉周围有危险(比如手雷)。 TLK_WOUND 当我已经受伤。 TLK_HIDEANDRELOAD 当我打算藏起来然后换弹。 TLK_PLYR_PHYSATK 当我被玩家扔过来的物体砸中了。
不是所有的 NPC 都会说所有的概念,也不是所有的 NPC 在相同的情况下都会说概念。有关完整列表,请参阅响应概念列表。
标准集(Criteria Set)
标准(Criteria)是一组条件,其中包含与对话者的当前状态相关的数据,以及每当请求尝试进行对话时概念的情况。它可以被解释为一组 键值。以下是一个由npc_alyx创建的标准集的例子,她试图说话因为她刚刚杀死了当前的敌人:
concept = TLK_ENEMY_DEAD NPC 尝试说话的概念。 map = d3_c17_07 当前地图的名称。 classname = npc_alyx 正在说话的NPC的classname。 name = alyx 正在说话的NPC的targetname。 health = 75 正在说话的NPC的生命值。 healthfrac = 0.9375 正在说话的NPC的生命值与它最大生命值的比值(默认 npc_alyx 的最大生命值是80)。 skill.cfg = 1 目前的 skill 级别。 timesinceseenplayer = 0.090000 从正在说话的NPC看见玩家时过去的时间。 distancetoenemy = 312.639679 正在说话的NPC距它当前的敌人的距离。 activity = ACT_RUN 正在说话的NPC正在执行的动画活动。 npcstate = [NPCState::Combat] 正在说话的NPC的 AI 状态。 enemy = npc_combine_s 正在说话的NPC的当前敌人的classname。 speed = 79.235 正在说话的NPC的移动速度。 weapon = weapon_alyxgun 正在说话的NPC握着的武器。 distancetoplayer = 211.240692 正在说话的NPC距玩家的距离。 seeplayer = 1 正在说话的NPC能否看见玩家。 seenbyplayer = 0 正在说话的NPC是否在玩家的视野内。 readiness = agitated 正在说话的NPC的readiness级别。 playerhealth = 100 玩家目前生命值。 playerhealthfrac = 1.000 玩家目前生命值的生命值与它最大生命值的比值。 playerweapon = weapon_shotgun 玩家握着的武器。 playeractivity = ACT_WALK 玩家正在执行的动画活动。 playerspeed = 0.000 玩家的移动速度。
这个概念默认没有任何修改器。上列表中所有的标准都是通用的且是为每个概念收集的。
上面列表中的标准可以通过规则的标准列表进行检查,并用于决定将哪个响应组用于所需概念。比如说:
- “enemy(敌人)”标准可用于选择对 TLK_ENEMY_DEAD 概念的正确响应。艾利克斯(Alyx)可以说“I took care of that soldier! 我解决了那个士兵!”或“I took care of that headcrab! 我解决了那个猎头蟹!”而不是做一般性说话。
- 如果她(艾利克斯)在击杀敌人时生命值小于20%,healthfrac 字段(field)可用于选择“Phew, that was close! 唷,太险了!”一句。
- distancetoenemy 字段可用于她在远距离或近距离杀死敌人时选择不同的语句。比如说“Those guys are scary when they get that close! 那些人靠得那么近就很可怕!”或“It's not easy hitting 'em at that range. 在那个范围内击中他们并不容易。”
尽管上面列出的标准是一般性的而不是针对概念而设置的,但标准在不同的情况下总是会有所不同,并且可能并不总是可用(比如说不在战斗中的 NPC 不会有 enemy 或 distancetoenemy 标准)。此外,地图制作者可以为特定的 NPC 或游戏中的所有 NPC 附加额外的标准。有关详细信息,请参阅 #Response contexts。
规则标准
根据规则是有一个标准列表的,这些标准会根据人物的标准集进行测试。当规则得到分数(point)时,会根据给定数据检查每个标准,并且该规则会收到成功匹配的标准的分数(point)。用于规则的标准获得分数由标准的权重决定。
标准在脚本文档中的定义格式(见下文):
criterion <criterion name> <key to check> <desired value> <optional: weight X> <optional: required>
参数如下:
- criterion name
- 不得与现有标准匹配。
- key to check
- 该标准将检查的人物标准集中的键值。
- desired value
- 条件集中的键的请求值。以下是使用格式:
- Numeric values: "0", "1", or "100".
- Inverse Numeric values: "!=0" (如果值不等于 0 则匹配)
- String value: "npc_alyx", "weapon_alyxgun", or "npc_combine_s".
- Enumerated value: "[NPCState::Combat]".
- 范围(Ranges):
- ">0" : 如果值大于 0,则匹配
- "<=0.5" : 如果值小于或等于 0.5,则匹配
- ">10,<=50" : 如果值大于 10 且小于或等于 50,则匹配
- ">0,<[NPCState::Alert] : 如果值大于 0 且小于 NPCState::Alert 的枚举值,则匹配。
注意:这默认不支持通配符。- weight X
- 这是一个可选参数,其中 X 是该标准在匹配时值所得的分数(point)。如果未指定,则标准默认为 1 point。
- required
- 这是一个可选参数,要想使用rules containing,则得需要此标准。如果所需标准未成功匹配,则包含它的规则所得分数会为0并立即跳过。大多数标准都使用此参数。
关于半条命2的一些实例:
- 下面的例子中定义了一个名为PlayerNear的标准 (这是用于检查与确保玩家在以对话NPC以中心500格的范围内)
criterion "PlayerNear" "distancetoplayer" "<500" required
- 下面的例子中则定义了一个名为IsCitizen的标准 (这是用于检查与确保说话的NPC是npc_citizen)
criterion "IsCitizen" "classname" "npc_citizen" "required"
- 下面的例中定义了一个名为IsMap_d3_c17_12的标准,(这是用于检查与确保游戏当在d3_c17_12.bsp上。这也有助于使一张地图中的所有citizen说出与其他地图不同的台词)
criterion "IsMap_d3_c17_12" "map" "d3_c17_12" "required"
- 下面的例子中定义了一个名为IsBob的标准,(这是用于检查与确保说话的NPC的目标名称为“bob”。这是游戏中独特的citizen,这个标准很容易让他说出特定的台词)
criterion "IsBob" "targetname" "bob" required
规则
一个规则 (Rule) 包括标准列表和至少一个响应组。该规则为成功匹配演讲者的标准集的每个标准接收分数。得分最高的规则将指向其中一个响应组,该响应组用于确定NPC将使用的确切语音。规则是在脚本文件中定义的(见下文)。使用以下格式:
rule <rule name>
{
criteria <criterion name 1> [optional: <criterion name 2> <criterion name 3> etc.]
response <response group name> [optional: <response group name 2> etc.]
[optional: matchonce]
[optional: applyContext <data>]
}
参数如下:
- rule name : 规则的名称。不得与现有规则匹配。
- criteria : 规则应根据的标准集进行评分。
- response : 如果此规则得分最高,则应选择的响应组列表。
- matchonce : 一个可选参数,如果指定了该参数,则一旦选择该规则一次,该参数将导致该规则被停用。
- applyContext : 应用响应上下文的可选参数。有关详细信息,请参阅#响应上下文。
例如,以下文本定义了一个名为 CitizenTalkStare 的规则。ConceptTalkStare 是一个检查说话的 NPC 想说的概念是否为“TLK_STARE”的标准。IsCitizen 是一个检查说话的 NPC 是否是公民的标准。NPCIdle 是一个检查以确保 NPC 的状态为“NPCState::Idle”的标准。如果此规则得分最高,则将使用的响应组为 CitizenTalkStare。
rule CitizenTalkStare
{
criteria ConceptTalkStare IsCitizen NPCIdle
response CitizenTalkStare
}
请注意,规则名称和响应组名称可以是相同的,因为规则名称只需要在规则之间唯一,而响应组名称只需在组之间唯一。
响应组
一个响应组包含一组可能的响应,以及一些可选的数据,用于定义如何使用这些响应。当规则选择了一个响应组时,从列表中选择一个响应并交给发言者使用。
响应组是在脚本文件内定义的(见下文)。使用以下格式:
response <response name>
{
[optional: permitrepeats]
[optional: sequential]
[optional: norepeat]
<response type> <response> <optional: ...>
<response type> <response> <optional: ...>
<response type> <response> <optional: ...>
}
响应组的参数如下:
- permitrepeats:如果指定,该组中的响应可以重复。如果未指定,默认行为是在重复任何响应之前使用列表中的所有响应。
- sequential:如果指定,将按照在组中列出的顺序使用响应。如果未指定,默认行为是从列表中随机选择响应。
- norepeat:如果指定,一旦播放了列表中的所有响应,响应组将被禁用。选择该响应组的任何规则都将对发言者返回无响应。
响应
响应是由系统选择然后由说话者使用的实际响应。响应组可以根据需要列出尽可能多的响应,每个响应都应该以下类型中的一个:
- speak : 该响应是一个音效脚本或原始音频文件。
- sentence : 该响应是sentences.txt中的一段句子
- scene : 该响应是一个
.vcd文件。详见场景编排的实现。 - response : The response is a reference to another response group which should be selected instead.
- print : 该响应是一段在
developer 1模式下位于说话者位置生成的占位用响应。 - entityio (存在于自
以来)[证实] : 该响应是一个I/O事件 ,它以说话者作为触发者(activator)对特定的实体触发IO事件,格式为entityio "<name> <input> <param>"。这与Followup Responses不一样,后者将会在下文进行介绍
响应后延迟参数
每个响应都支持各种可选参数。
- nodelay:在响应完成后,允许发言者立即再次发言。
- defaultdelay:在响应完成后,发言者将在2.8到3.2秒之间的随机时间内不被允许发言。
- delay X:在响应完成后,发言者将在X秒内不被允许发言。X也可以是一个范围,例如"5.5,7.5"。
- weapondelay X:当响应开始时,发言者将在X秒内不能开火武器。默认仅在HL2 NPC盟友上可用。
- speakonce:防止重复使用响应。
- odds X:如果指定,选择此响应时,发言者有可能保持沉默而不是说出响应。odds 是取消响应的机会(0-100%),例如25表示不说话的几率为25%。
- respeakdelay:如果指定,除非概念在至少X秒内没有被说过,否则不能使用此响应。X也可以是一个范围,例如"5.5,7.5"。
- soundlevel:如果指定,应该在响应中使用该声音级别,而不是默认的SNDLVL_TALKING。
- displayfirst:如果指定,应首先使用此响应(忽略权重参数)。
- displaylast:如果指定,应最后使用此响应(忽略权重参数)。
- weight:如果指定,用于加权选择列表中的响应。默认情况下,所有响应的权重均为1。请注意,响应在选择了所有其他响应之前不会重复,这意味着一旦选择了所有高权重的响应,系统将只计算权重较低的响应。可以通过permitrepeats来抵消这一点。
- noscene:阻止响应系统为speak响应创建自动生成的场景。
- stop_on_nonidle:当响应被说出时,当NPC进入非空闲状态时停止场景。在Source 2013中,仅在HL2剧集模组中的scene响应上起作用。
- predelay:当选择响应时,直到过了X秒才会实际说出来。仅在scene响应上起作用。X也可以是一个范围,例如"5.5,7.5"。
例如,下面的响应组由市民用于回应TLK_STARE概念。市民将按照它们在列表中的顺序使用响应(由于 sequential 参数)。每个被选择的响应都会停止NPC发言一段随机时间,介于10到20秒之间。
response "CitizenTalkStare"
{
sequential
scene "scenes/npc/$gender01/doingsomething.vcd" delay "10,20"
scene "scenes/npc/$gender01/getgoingsoon.vcd" delay "10,20"
scene "scenes/npc/$gender01/waitingsomebody.vcd" delay "10,20"
}
脚本文件
/scripts/talker/response_rules.txt 是基本脚本文件,包含响应规则系统使用的所有条件、规则和响应组。该文件还可以包括使用 #include 关键字的其他文件,这允许你根据 NPC、地图等干净地划分规则。请注意,一些实体,如 env_speaker,指定了自己的脚本文件,其中包含实体要使用的条件、规则和响应组的子集。有关火车站终端公告使用的示例,请参见 scripts/talker/terminal_pa.txt。
响应上下文
响应上下文类似于地图作者设置的标准。它们通过“Response Contexts”(ResponseContext)键值或AddContext输入进行设置,格式如下:key:value;key:value;key:value;……其中key是“键”,value是“值”。
后续响应
求生之路引入了“后续响应”,即在响应后发生的事件。它们被触发为响应参数,类似于odds、predelay等。
- fire:通过I/O系统使用发言者作为激活器和调用者触发一个输入。格式为
fire <target> <input> <delay>。不支持参数。 - then:导致在实体上分派另一个响应。格式为
then <target> <concept> <response contexts> <delay>。用于使角色动态地相互响应。
可以使用一些独特的目标名称:
- self:发言响应的实体。
- subject:使用发言者“Subject”上下文中找到的实体名称(如果存在)。游戏为info_remarkable响应设置了这个。
- from:使用发言者“From”上下文中找到的实体名称(如果存在)。游戏将其设置为上一个后续响应者的名称,允许后续响应来回弹跳。
- any:分派到
rr_followup_maxdist(默认为1800)中存储的任何有效响应者。 - all:分派到
rr_followup_maxdist(默认为1800)中存储的所有有效响应者。
来自Left 4 Dead 2中的示例coach.txt:
Response _c1m4startelevator4bCoach
{
scene "scenes/Coach/WorldC1M4B01.vcd" then mechanic _c1m4startelevator5a foo:0 -2.313 //Son, you got a DEAL.
scene "scenes/Coach/WorldC1M4B02.vcd" then mechanic _c1m4startelevator5a foo:0 -5.790 //Ha HA! All the way to New Orleans! Baby, that sounds like a PLAN.
scene "scenes/Coach/WorldC1M4B05.vcd" then mechanic _c1m4startelevator5b foo:0 -6.334 //Normally I wouldn't do this. But in these circumstances, I think Mr. Gibbs, Jr. ain't gonna mind.
scene "scenes/Coach/WorldC1M4B10.vcd" then mechanic _c1m4startelevator5b foo:0 -2.685 //Forgive us Jimmy, but we need your car.
}
高级响应规则的使用
响应系统可以以许多高级和专业的方式使用。以下是一些用于系统高级用途的技巧和窍门:
- 使用
DispatchResponse触发自定义响应 - 实际上,任何可以在脚本文件中找到的响应概念都可以传递给NPC,只要它不限于AI预定义的TLK_*概念。
- 例如,您可能希望在玩家成功解决谜题的一部分时,旁观组中的NPC发表祝贺的响应概念。
- HL2中的玩家盟友还具有更高级处理和条件的
SpeakResponseConcept输入。
查看EP1/EP2中Alyx的响应脚本或L4D幸存者的响应脚本,以获取更多高级响应系统使用示例。
调试
注意
- 要能够使用响应系统,必须使用由 CAI_BaseActor 类派生的 NPC。
- 参见
scripts/talker/npc_*.txt文件以获取特定 NPC 响应规则的示例。 scripts/talker/response_rules.txt是响应规则系统的列表。如果为新 NPC 添加新的响应规则脚本文件,请确保在scripts/talker/response_rules.txt文件的末尾通过 #include 语句包括该文件。
另请参阅
(译注:以下链接链接到英文页面)
外部链接
- Elan Ruskin 在 GDC 2012 上的“用于上下文对话和游戏逻辑的规则数据库”演示文稿,它描述了响应系统及其演变。 (幻灯片:[1])
- Two Bots One Wrench: Environmentally Responsive Speech Video, 演示视频 #1
- Two Bots One Wrench: Memory And Context, 演示视频 #2
- Two Bots One Wrench: Conversation, 演示视频 #3