这篇是「如何制作一款开放世界游戏」系列实战篇之一,行人主题的下篇。上篇讲的是调度与决策——到「产生任务槽」为止:世界基础层、实体表示、人口生成与剔除、行为级 LOD、感知—决策—任务流水线。这一篇讲另一半:执行。 一个挂在任务槽上的「逃跑」任务,如何转化为实际执行中的 NPC 行为?街边抽烟、长椅就坐等场景行为实体的生成来源是什么?NPC 的走路动画、被撞倒的物理反应,该自建还是复用引擎?
材料同样来自对一款成熟商业开放世界游戏引擎与客户端代码的长期源码级逆向阅读(约 700+ 篇源码级笔记),对照的是同一个 UE5 原型工程。写法上每个子系统走同一条三段线索:原版怎么设计 → 为什么不套现成方案(或该复用什么) → 原型里怎么实现/规划。
一个必须先说透的前提:本篇是行人主题里原型落地最薄的一篇。 上篇的基础层进入稳定状态、感知流水线有真实函数体;而本篇涉及的具体行为与表现层——具体任务行为、场景系统、动画、ragdoll——在原型里几乎全部未开始。所以本篇的定位是「原版设计 + 迁移地图 + 复用定调」:明确哪些结构值得迁移、哪些直接复用引擎、哪些属于后续专题,并标注当前尚未实现的部分。但「地图」不等于「概览」——本篇①段已经细化到任务名和状态级:响应家族拆到三段分工、场景生态拆到五件套、ragdoll 拆到阶梯与桥;规格的精度,就是这篇文章的交付物。
诚实边界:动画混合树内部、寻路内核、任务树调度算法、行为化 ragdoll 的算法内核,都是逆向读不到或本系列未深挖的盲区,碰到一律标注。其中「各物种运动」「ragdoll 物理表演」「响应反应家族」三块,原版侧的笔记厚度足够单独成篇,本篇只做定调,深挖留给后续专篇。
引言:从决策状态到连续行为表现
术语说明:本文统一使用“叶子任务”指代任务树末端的具体执行任务;使用“过渡包装层”指代负责把当前语境整理成可执行条件的中间层。它们分别对应执行职责与进入条件,不是新的行为系统。

上篇第六章把一条流水线讲到了「事件被裁决、变成一个挂在任务槽上的待执行任务」为止。但一个任务槽只是意图——「逃跑」两个字不会自动进入执行状态。 它还要变成:一条离开威胁的路径、一段越来越急的步态、被撞上时一个踉跄、以及(如果它路过一个场景点)一次沿途进入场景点完成短时休息。上下两篇的接口就是那个任务槽:上篇保证槽里装的是「经过裁决的意图」(裁决过、去重过、可溯源),本篇回答「意图怎么被兑现而不失控」——四章分别对应兑现的四个侧面:执行的组织(一)、内容的供给(二)、身体的驱动(三)、物理的接管(四)。四个侧面对「一个活人」缺一不可——组织缺了行为会乱、供给缺了街会空、驱动缺了人会滑步、接管缺了人会像布偶——但它们的建造可以完全异步,这正是把执行侧拆成四章而不是一章的理由。
这一半的工程量一点不比上篇小——按母库的覆盖粗算,行人执行侧(任务族、场景生态、受击任务族)的函数级笔记篇数不亚于车辆全部——但它的建造性质完全不同。上篇讲的调度与决策层,几乎每一层都值得贴着原版语义自建——所有权、门控、预算、因果链,都是现成框架给不了的。而本篇讲的执行与表现层,恰恰是复用引擎设施最密集的地带:走路的动画不必自己写混合树,倒地的物理不必自己写求解器。难点从「自建什么」变成了「自建与复用的接缝画在哪」——行为层产生的「运动意图」在哪里交给动画系统、物理表演在哪里接管骨骼、场景点的数据层怎么和自建的任务运行时对话。整篇读下来会发现,四章其实都在回答同一个句式的问题:「X 交给 Y 之后,X 还剩下什么责任」——任务交给叶子、行为交给场景、意图交给动画、身体交给物理;每一章的答案都是「剩下进入条件、期间观测、收回出口」,只是 X 和 Y 换了名字。
文章分四章。第一章讲任务执行——任务槽下面那层「真正做事」的结构,这次把「响应反应家族」按母库的函数级笔记拆到了选择器/过渡包装层/执行者三段;第二章讲场景生态——「在对的地点做对的事」的数据驱动机制,补上了聚簇、封闭区、实体覆盖校验这三个世界侧生产者;第三章是定调章(locomotion 动画,按用户定调保持轻),第四章讲 ragdoll 物理——结构级已经能讲得相当深:受击不是一个任务而是一族,交接协议、平衡阶梯、回动画的桥都有具体的任务名。最后给出迁移清单。
材料口径:本篇①段对照的函数级母库笔记包括被动恐惧任务族(举手/掩蔽)、通用受击任务族(踉跄/倒地)、场景聚簇与约束运行时——加上角色篇上篇已引的感知流水线,行人执行侧的原版证据同样厚实;薄的是原型侧,这一点每章③如实标注。
读完四章,几个问题会变得清楚:一声枪响之后,「吓蹲下」这个行为经过哪三层任务分工才落到动作;一个坐长椅的 NPC 被惊扰后如何恢复原场景占用;「被车撞飞」在任务系统里是什么身份、撞完怎么爬起来接回动画;以及为什么本篇敢把动画一章压成定调、却把 ragdoll 一章写到阶梯级。
UE5 实现实操在后续落地篇:本篇(与本系列所有方案篇)的定位是设计与迁移决策——原版为什么这么设计、哪些自建哪些复用、接缝画在哪。每篇方案篇都对应一篇落地篇,讲 UE5 工程里实际怎么跑——代码走读、接引擎子系统的具体做法、踩坑与验证——后续陆续补上。
一、任务执行:从任务槽到行为


这一章要解决的问题:一个 Pending 的任务槽,如何转化为可执行的行人行为?任务执行层的结构长什么样,才能既完成任务、又随时能被更高优先级的事件打断?以及最容易被低估的一问:短时「惊吓」反应为何需要三层任务分工?
① 原版机制
上篇讲过,任务在智能流水线的固定一步(process tasks)里推进,且一个 NPC 同时有几棵并行的任务树(主/次/移动/动作)。这一章看树里面:一个任务是可打断、可重试、可回退的分层状态机。 「不是函数」值得辨析一下:函数的生命只有调用栈那一瞬,而任务要跨帧活着、要在中途接受外界变化(目标挪了、被打断了、资产到了)、要在死前完成状态收敛——任务是「跨帧任务对象」,那些义务(生命周期、出口、溯源)正是本篇反复出现的全部纪律的载体。
这个模式在本系列已经出现过两次,这里正式点破它是通用范式:车辆篇讲的进出车链(外层 FSM 管策略、叶子任务管执行)、车辆篇下篇讲的驾驶执行栈(路线所有者 → 局部避让 → 控制写入),都是同一个形状——外层任务拥有策略与状态编排,底下挂一串职责单一的执行任务,每个叶子有自己的成功/失败出口。 行人侧的任务家族对位:一个「逃跑」任务,外层管「往哪逃、要不要回头看、逃到什么程度算安全」,底下的叶子管「沿这条路径移动」「播放这段受惊动作」。上层不断重塑目标、下层执行当前一小步——这让任务在任何一步都能被打断:外层状态机知道自己走到哪,被打断后要么恢复、要么干净退出。行人侧的执行叶子比车辆侧多一类跨介质款:逃跑的移动任务可能要在「徒步逃跑」和「上车逃」之间切换——于是行人的任务能持有车辆篇讲的进出车链作为子链,两个主题的任务树在执行任务层直接握手,这也是当初把「进出车」放在车辆篇、把「逃跑策略」放在行人篇的所有权依据:链归关系的权威方,选择归行为的发起方。
原版行人侧的任务家族非常庞大,其中几族值得点名(它们各自的厚度都够单独成篇,本篇只标出位置)。点名之前先接上篇的线:这些任务全部经由事件桥进入任务槽——族的划分其实就是「响应表右列的分类」:同一张表,左列是事件类型,右列按族指向不同的任务构造;族是路由的目的地聚类,不是运行时的隔离墙,不同族的任务在同一批槽里竞争同一套优先级:
- 移动与运动家族——各物种的 locomotion(人/四足/鸟/游泳),任务层产生「以什么步态往哪走」,底下接运动系统(第三章定调)。行人的移动任务和车辆篇的控制写入者是对位物:任务不摆骨骼,任务只下发「去哪、多急」,骨骼归运动系统——这条分界预告了第三章那道接缝。
- 响应反应家族——逃跑、掩蔽、躲避、举手、对峙、惊吓:NPC 被事件命中后「像人一样反应」的那批任务。这一族的内部结构,拿「被动恐惧」这一支就能讲清(母库函数级笔记):最上面是聪明逃跑(SmartFlee)这个高层威胁策略选择器——它拥有威胁评估、路线与模式选择,并在「真逃跑」和几种被动恐惧(举手投降/原地掩蔽/车内掩蔽)之间做选择,但不拥有任何一种的具体执行。选择器单独成层的理由,在「换选项」的成本上看得最清:给世界加一种新恐惧反应(比如「拍下视频再跑」),只是给选择器加一个分支加一个新执行者,四种旧反应一行不动;若选择逻辑散在各执行者的进入条件里,每加一种反应都要重理一遍全部条件的互斥关系;中间是过渡包装层——「被枪指着」的反应的过渡包装层只做三件事(识别被瞄准的语境、决定要不要先下车、把 ped 摆到正确的物理语境后创建执行者)。为什么中间必须有这层、不能选择器直接建执行者?因为语境准备本身会失败、会花时间:司机被枪指着,得先完成一整条下车链(车辆篇的编排)才能举手——这段「从现状到可执行状态」的过渡有自己的状态机与失败出口,并进选择器会让策略层染上执行细节,并进执行者会让「举手」被迫理解车。过渡包装层是进入条件的专属职责;最下面是真执行者——举手任务拥有投降动作的状态机、计时、朝向、被打断的处理,以及联机克隆的状态连续性。执行者的入口不止选择器一个:脚本可以直接注入举手(过场需要)、事件路由可以直接请求举手(特定事件的既定响应)——多入口、一执行者,运行时只保留一份投降行为的执行定义,不同调用方共享同一实现。三段式和车辆篇的「选择器/过渡包装层/执行核」相同——威胁响应和警车围堵,在任务组织学上是同一种组织结构。这一支还有一个精妙的交叉:「原地掩蔽」的长时间表演,走的是场景系统——掩蔽过渡包装层解析出一个「原地反应」场景路径,把表演委托给场景执行任务(下一章的场景执行任务模型);一个吓得蹲下抱头的路人,和一个坐长椅的路人,底下是同一套「按场景点表演」的运行时。恐惧复用已有机制,变化只在内容。 这里还要区分两张表:上篇讲的决策器加权,答的是「这个刺激值不值得反应」(可以合法地不);这里的选择器,答的是「决定反应之后,反应成什么」。「要不要」和「成什么」是两次独立的裁决,分开之后,「胆大的人也会举手」(要:是;成:投降)这类组合才表达得出来。
三层总结:这三层真正解决的是三个变化速度不同的问题:选择变化最快,语境变化其次,表演变化最慢。把它们拆开,才能让调策略、换语境、扩内容互不牵连。
- 环境行为家族——用场景点、点间游荡、半径内游荡(第二章展开)。
三族合起来还覆盖了一条时长谱系:半秒的受击晃动、几秒的举手、几十秒的掩蔽、几分钟的用场景、无限期的游荡——全部是同一套任务槽/优先级/生命周期在承载,没有「短反应走特殊通道」的旁路。上篇讲的几棵并行任务树在这里显出用处:瞬时反应可以占动作树、不打断主树上的长行为(边逃跑边回头看一眼),时长的差异被「并行 + 优先级」吸收,而不是被特殊机制吸收。
三族的迁移顺序顺着依赖走:移动任务最先(逃跑和用场景都要会走路)、环境行为第二(它只依赖移动加场景数据)、响应家族最后(它要打断前两者,得先有可打断的对象)——和车辆篇「先控制写入者后战术包装」对位:被消费的先做,消费别人的后做。 三族落地后再回头看上篇的裁决层,整条「感知→裁决→执行」流水线才第一次端到端跑通——那也是行人主题的「第一次端到端闭环」时刻。
本章的三个问题至此都有了答案:任务槽变成行为,靠「策略 FSM + 叶子任务」的组织;既做完又可打断,靠出口精确的叶子加记得返回点的外壳;「吓一跳」值得三层分工,因为选择、过渡、表演的变化频率完全不同——选择随设计调、过渡随语境变、表演随资产换,三层各自演化,才撑得起十年的内容累积。
这一章的意义:任务执行层的价值不在某个具体行为的算法,而在「外层策略 FSM + 叶子任务」这个可打断、可回退的通用结构——它在行人、进出车、驾驶栈、威胁响应四处反复出现,是整套 AI「既能做完事、又随时能被打断」的结构根基。「选择器不执行、过渡包装层只准备语境、执行者只表演」的三段分工,让每一段都可以被单独替换:换一种投降动作只动执行者,加一种「先锁车门再举手」的语境只动包装,调整投降倾向只动选择器——行为的丰富度长在分工上,不长在某个大函数的分支里。
② UE5 复用与自建边界
先看规模:响应家族按母库的覆盖有二十多篇函数级笔记,本篇只拆了被动恐惧一支——但三段式在其余支上同样成立(战斗支的「威胁响应选择器→具体战斗任务」、调查支的「响应包装→走过去看看的执行」),这也是敢用一支代表全族的依据:族的多样性在内容,不在组织学。
UE 的行为树/状态树能不能直接当这层用?能承载一部分——尤其 StateTree 的「状态+进入条件+转移」形状,和外层策略 FSM 相性不差,把它当单个任务内部的状态机载体是合理选型;但「任务之间」的那层语义(几棵并行树、槽位抢占、跨任务溯源)在任何现成树里都没有对应物,还是要自建的槽位系统来管。现成树管一棵树里面,自建槽位管几棵树之间——边界这么画,两边都用在长处上。此外有两个语义要点得自己守住:
- 打断语义:原版的打断不是「换个分支」,而是「更高优先级的事件通过响应表路由进来、抢占任务槽、被抢占的任务走自己的干净退出路径」。这条链的上半段(事件→裁决→路由)在上篇已经自建,执行层的任务结构必须和它对齐——用行为树也得把「槽位优先级 + 生命周期 + 来源溯源」这套语义嫁接进去,否则打断就退化成「硬切」,回退逻辑没有安放处。「硬切」的代价值得具体化一次:坐着的 NPC 被硬切进逃跑,没人负责把「我占着长椅场景点」的账清掉——场景点从此显示被占、再没有 NPC 能坐;长时间运行后,城市长椅会持续处于错误占用状态。行人侧的「失效场景占用」和车辆篇的「失效车辆占用」是同一种病,药方也相同:每次状态变更有权威方、被打断有退出路径、外壳记得返回点。
- 执行叶子该复用的尽量复用:执行任务内部的「沿路径移动」可以直接消费 UE 的寻路与移动组件,「播放动作」直接走动画系统——自建的是执行任务的编排结构(什么时候进、成功失败怎么出),不是执行任务内部的现成设施。
③ 原型状态与规划
诚实说清楚:任务执行层在原型里目前只有「槽位推进」的骨架,具体行为一个都还没接。 上篇讲过,ProcessIntelligence 目前推进的是计数器和槽位生命周期状态,头文件明写「skeleton-level semantic controls only; they do not execute subtasks, movement, animation, or vehicle entry」。
迁移规划上,这一章给出的决策是:
- 任务的分层 FSM 结构自建,贴着「外层策略 + 叶子任务」的范式,执行任务出口对齐系列一贯的精确枚举纪律(成功/失败/被打断各是可区分状态)。落地形状可以直接对标车辆篇下篇的进出车编排——那套「桥→门→执行→回写→收尾」在行人侧同样适用:行为叶子执行前过前置门(有路可走吗)、执行后回写任务槽生命周期、被顶替时走既有的中止链;车辆侧已经将这套编排实现并完成近两百条测试,行人侧可沿用同一结构。
- 执行任务内部复用引擎:移动消费 UE Navigation + 移动组件(寻路内核是盲区,当黑盒用),动作播放走动画系统(第三章)。
- 响应反应家族按三段式逐段迁移:选择器层对应原型已有的响应表(上篇讲的
响应表状态——「某类事件映射成哪棵树、什么优先级、什么任务」正是选择器的骨架);过渡包装层与执行者层 ③ 未开始,但执行者优先(先有一个能够实际执行举手行为的任务,过渡包装层和选择器才有可供选择的对象)——和车辆篇「先控制写入者后战术包装」同一个自底向上顺序。
诚实边界:本章③里已落地的只有响应表骨架(上篇详述),其余全部是规划。任务树内部的仲裁调度算法(多棵树怎么抢占)沿上篇口径,仍是盲区;被动恐惧之外的响应支(战斗、搜索、调查)母库已读但本篇未展开,留给后续专篇。
二、场景生态:场景点如何驱动环境行为


这一章要解决的问题:街边抽烟、长椅就坐、摊位经营和靠墙停留等「在特定地点执行特定行为」的实体,其生成机制是什么?显然不能依赖逐点手工布置。以及更工程化的一半:点绑着的椅子可能没流进来、点可能落进脚本禁区、四个点需要组成一组牌局——数据侧的点和运行时世界之间,由谁负责一致性校验?
上篇讲了 NPC 怎么被生成、怎么感知—决策—产生任务。但那样生成出来的默认是「游荡的路人」。一座城市的「环境活力」还需要「在对的地点做对的事」的人——这一章讲这层。它是本篇原版证据最厚的一章,也是整个行人主题里最靠上、原型里最靠后的一层。
① 原版机制
不能手摆,所以原版用一套数据驱动的场景点(scenario)系统:世界里预先烘焙了成千上万个「场景点」,每个点带一份元数据——「这个点是一个『坐长椅』的点」「那个点是一个『靠墙抽烟』的点」。运行时,人口系统在这些点上生成 NPC,并直接给它装上对应的行为。「成千上万」这个量级决定了它的一切工程形态:点必须随区流式(整个场景点表不应一次性载入内存)、点的激活必须按距离(角色篇的「成本即距离」)、点和实体的绑定必须容忍流式时差(所以有覆盖校验)——场景系统的复杂度大半不来自「坐下」这个行为,来自「几万个坐下的位置」这个规模。
这套系统被拆成几个职责清晰的所有者:
- 场景点存储——持久的点/区存储,按区流式加载。哪里有哪些点,是它的事——只此一事:它不判断点该不该活跃(协调器的事)、不知道点上会发生什么(元数据的事)、更不管点上的人(任务的事)。
- 场景元数据——「一个『坐长椅』点具体意味着什么行为、动画、条件」的数据库。「条件」这一栏让点自带开合逻辑:一个点可以只在某些世界状态下有效——于是「同一个位置白天是报摊、夜里没人」不需要脚本轮班,点自己按条件开合。世界的作息表写在数据里,不写在更新循环里。
- 场景运行时协调器——每帧的运行时核心:刷新场景条件、流式压力、聚簇、实体覆盖队列、车辆场景生成、扩展范围、非区域点的空间数组更新……
三者的关系照例是「数据/元数据/运行时」的三分:存储答「哪里有点」、元数据答「这种点意味着什么」、协调器答「此刻哪些点该活」。和交通篇的「路网数据库/路口模板/路口注册表」逐位对应——「静态位置 + 作者规则 + 动态活跃」的三件套,是这套引擎给一切『世界里的可交互位置』的标准建模,场景点和路口只是它的两个实例。
其中最能体现设计意图的是它的分发桥,把「一个抽象的场景点」变成「一个真的在做这件事的 NPC」,分三步(注意三步的产物依次是:任务类、带外壳的任务、装着任务的活人——桥的每一步都只加一层,层层可测):
- 类分发——把场景信息映射成一个具体的任务类:用场景、半径内游荡、点间移动、尸体场景……元数据说「这是哪一类」,这一步造出对应的具体任务。注意这一步和上篇事件桥的「响应工厂」是同一种构件——「数据标识 → 任务实例」的映射表;场景系统和事件系统各维护一张,格式雷同、内容不同。第一章讲的掩蔽复用场景,技术上就是「威胁响应的选择结果指向了场景这张表里的一个条目」。
- 控制外壳包装——把裸场景任务包进一个更高的控制外壳(比如「未警觉」外壳、「乘火车」外壳——后者是个好例子:乘客的「坐着」是场景任务,但「到站要下车、坐过站要处理」是乘车语境特有的策略,归外壳)。为什么要包一层?因为一个坐着的 NPC 不能只会坐——它还得能被打断、被吓到、感知周围。控制外壳提供的就是这层「日常态」的骨架。外壳还有一项容易漏看的职责:连续性。母库对被动恐惧一族的笔记里点名,「未警觉」外壳保存着「正在场景化掩蔽」的标志和返回点——一个坐长椅的 NPC 被吓到蹲下抱头(掩蔽也走场景执行),威胁过去后,外壳凭这份连续性状态把它送回长椅,而不是让它茫然站在原地重新随机决定去向。「被打断之后回得去」,一半靠任务的干净退出,另一半靠外壳记得「你原来在过哪」。
- 场景生成桥——这和普通的「生成一个默认游荡 NPC」不同:它做场景专用的预生成校验、选/校验模型、碰撞检查、调人口系统走生成合法性契约、生成后装上场景控制任务。「调人口系统走合法性契约」这半句是关键——场景生成不绕开人口预算:场景点想出人,同样要过人口系统的产出闸门(上篇第四章的成对预算),环境行为不能绕过人口预算约束。场景系统调用人口系统,但不改变人口系统的资源约束。
还有一个容易忽略的能力:这个协调器不只处理「按点生成」,它还能把一部分随机生成的普通路人「升级」成使用默认场景——一个本来只会游荡的路人,可能被判定「适合去用一下旁边那个场景点」,从而自然融入环境。这让环境行为不完全依赖预烘焙的点,也有随机的活力。「升级」和「按点生成」是同一份内容的两个入口:前者把已有的人引到点上(路人恰好路过报摊,顺势看报),后者在点上造新的人(报摊后面得站个摊主)——两个入口填同一批点,街景的密度就能随人流自适应,而不是每个点都靠新生成来填。两个入口的成本结构也互补:生成花人口预算、撮合花扫描开销——预算紧张时提高撮合比例,人流稀疏区域由生成机制补足,同一批点在两种供给之间自动找平。
协调器周边还站着四个世界侧的生产者与约束,按母库的运行时笔记逐个点名:
- 聚簇:一组场景点可以被编成一个「簇」,由一个小型世界侧 FSM 统一管理——校验成员点、收集并请求流式依赖、排期车辆生成点、在成员点上生成人或车、跟踪已生成的成员、统一 despawn、再加密度与玩家影响的门(密度门=玩家周边这类内容已经够多就不再开新簇,玩家影响门=玩家的行为可以暂时压制某些簇——成组内容也受人口经济学管辖,不因为「是设计好的场面」就有超发特权)。「一桌四个人的牌局」要么整桌出现要么整桌不出现——单点各自为政会生成出「牌局只来了一个人」的破碎场面,簇就是为「成组的可信度」而生的编队级生产者(和交通篇的路障装配体同族:一个管生成侧,一个管派遣侧)。「流式依赖统一收集」这半句解释了为什么簇必须是 FSM 而不是一次函数调用:四个人两辆车的模型不会同帧到齐,簇要在「等资产」这个状态上停留可观的时间,等齐了才放行生成——又一处「等待是显式状态」。
- 封闭区:一张全局的「场景禁区」体积表——添加/移除禁区、「这个点在不在禁区里」、「活跃场景该不该因禁区退出」。生成侧查它决定「这里还能不能出人」,活跃侧也查它——脚本圈一块禁区,里面正在抽烟的 NPC 会收到「该走了」的裁决,而不是只有新生成被挡。约束对存量与增量同时生效,禁区才是真禁区。它的主要客户是内容制作本身:过场要清场、任务要独占一条街、玩家买下的房产周围不该有人蹲着——「把一块区域从环境系统手里临时收回」是内容侧的高频操作,值得一张专门的表,而不是每个脚本各显神通地删 NPC。
- 实体覆盖校验:场景点常绑在流式的世界实体上(长椅、报摊),而实体可能没流进来、坏了、或整个室内还没加载。一套专门的加载后校验队列逐个核对这些绑定,状态分档精确到「工作中/勉强/损坏/道具损坏/室内未流式」。「点还在、椅子没了」是流式世界的常态,这层校验就是数据与世界之间的对账员——注意「勉强(struggling)」这一档:校验的产出不是「能用/不能用」两态,连降级可用都是一个显式状态,内容侧能按档决定「勉强的点少出人」而不是一刀切。分级状态的纪律,连资产对账都不放过。
- 车辆生成器:停在路边的车、场景点要用的车,由一条独立的车辆侧生成管线负责(按距离排期、检查人口余量、选合法模型、正确地摆上路面、最终就绪检查、入世)——「正确地摆上路面」五个字底下是贴地、对齐车道方向、不与既有物件穿插这一类繁琐细节,生成的可信度一半耗在这步;而「排期→就绪检查→入世」的三拍结构,和聚簇的「等资产再生成」一样,把生成做成了可等待、可取消的过程而非一次调用。它是与人口系统平行的世界生产者,产出的车之后归车辆 AI 管。「场景里的车」从生成那一刻起就走正规生成管线,不是场景私产。
补一句实施顺序:五件套不必一次到齐。最小可用子集是「点存储 + 分发桥 + 外壳」——有这三样,街上就有坐着抽烟的人;聚簇(成组可信度)、封闭区(脚本管控)、覆盖校验(流式健壮性)、车生成器(带车场景)是四个独立的增量,各自解锁一类内容,谁先谁后看内容侧的需求排期。生态可以按件交付,这也是把它拆成五件的工程动机之一。
而在生成的最初一刻,一个新 NPC 拿到它第一个行为的地方,是人口系统的一个专门交接点(下称 实体接入点)——由它计算初始的游荡/默认任务、装上默认任务、或可选地应用默认场景信息。生成(谁造出这个实体)和第一个行为(它一出生该做什么)是被刻意分在两个所有者里的:工厂只管造,人口的交接点才管「它的第一份行为任务」。把这两件事分开,是因为「怎么造一个实体」和「这个实体一出生该做什么」是两个完全不同的关注点——一旦揉在一起,工厂就会被灌入大量行为逻辑,越来越重。反过来验证这条边界的价值:本篇讲过的所有「进入世界」的通道——环境生成、场景点生成、聚簇成组生成、掩蔽时的场景绑定、甚至交通篇的路障警员——造的方式五花八门,「装上第一份行为任务」全部走同一类交接点;行为任务的种类在膨胀,交接的形状十年不变。
这一章的意义:一座城市的「环境活力」不是依赖手工布置的,而是把「在哪、该做什么」外化成可流式加载的数据点,再用一条清晰的分发桥把数据点转化为可被打断的运行时 NPC 行为。数据管内容,代码管将内容转化为运行时行为——这条界线让策划和程序能并行。这次还补上了一层:点的周围还站着成组生产(聚簇)、全局约束(封闭区)、流式对账(实体覆盖校验)、平行的车辆生产线(车生成器)——「环境活力」是一个五件套的生态,单看「点+任务」会低估它一半的工程量;而五件套按件交付的路径(最小子集三样先行)已在③给出,低估不应转化为对实现规模的误判。
② UE5 复用与自建边界
这一层和上篇几章不同:「世界预置交互点」这个数据层,是少数值得复用现成设施的地方。 UE 的 Smart Objects(一个点定义「这里可以做一件事」,NPC 来认领并执行)核心思想和场景点几乎一样,还带编辑器工作流和空间查询——这块没必要自己造,原型也计划直接用它做点存储。注意它不是 Mass 那种「实体运行时」框架,而是一个数据/查询层,正好可以挂在原型自建的运行时上,两者不冲突。这里的边界很明确:不使用 Mass 不等于排斥现成设施——排斥的是「让框架接管运行时调度和所有权」,欢迎的是「纯数据/查询层的复用」。复用的精确边界顺手画一下:Smart Objects 拿走「点在哪、被谁占着、怎么查」;「占用之后发生的一切」——外壳、连续性、打断、返回——留在自建任务系统里;认领接口两侧各是各的主人,和「GPS 借小地图画线」是同一种协作形状。
但原版协调器的几处主动性,现成方案不给,仍得自建:
- 可打断的「控制外壳」——认领机制让 NPC 去执行一段行为,但「执行时还能被事件打断、被吓到、无缝退回日常态」这套外壳,要靠把它嵌进上篇第六章那条感知—裁决—任务流水线里(而那条流水线正是自建的);外壳里的返回点连续性(被打断后回原点)同样是自建项——认领系统只管「占用与释放」,不管「回不回得去」。外壳的种类预计不多(未警觉一个通用款,加乘车这类语境特化款按需增补),但它是场景内容能否规模化的杠杆:一个外壳服务所有场景任务,外壳每多一分健壮,几万个点的内容就同享一分。
- 主动撮合——「人口系统主动把闲逛的路人引导到附近的点」这种主动性,认领机制不提供。撮合的价值在密度经济:同样一条街,靠新生成填点要多维持 N 个 NPC,靠撮合只是给已有 NPC 换行为任务——预算不变、街景变密;实现上它是一个低频扫描(附近有闲人+附近有空点→下发「去用那个点」的意图),形状和派遣的「事件找响应者」相同,规模小得多。
- 统一的运行时协调器——聚簇、实体覆盖、扩展范围这些每帧的细粒度职责,现成生态里有零件但没有一个统一的「场景运行时协调器」。
- 聚簇与封闭区——成组生成的 FSM 和全局禁区表都是纯业务结构:聚簇可以和交通篇的路障共享「装配体」基类形态(成员句柄+编队策略+生灭状态机,一个管生成侧一个管派遣侧);封闭区是一张带增删查的体积注册表,形状同路网的限速区——两个都不难,难的是记得「约束要对存量也生效」(禁区里正在表演的场景要被清退,不只是不再生成)。
- 实体覆盖校验——对应到 UE,就是「场景点资产引用 + World Partition 流式」之间的对账:点引用的实体没流进来/坏了/室内未加载,各是一档精确状态。这层在 Smart Objects 之上,得自建。
③ 原型状态与规划
先说清楚:场景系统在原型里目前还没实现——它是行人主题所有子系统里最靠后的一层。 迁移路线图把重心放在「先把实体运行时、物理、Ped/Vehicle/Object 骨架立稳」,场景是这些之上才接的东西。但基础层已经为它准备好了几处关键的接入点,值得指出这层将来会如何延伸出来。
- 「可打断的控制外壳」有现成挂点:上篇第六章那条流水线已经把「日常态任务可以被更高优先级事件打断」做进了任务槽的优先级 + 生命周期 +
bTasksSuppressed+ 事件桥的去重逻辑。将来一个「坐长椅」的场景任务,就是挂在Primary树上的一个槽;一个更高优先级的「被吓到」事件通过事件到任务的桥接接口路由进来,就能自然打断它——而且事件桥里那个「已 Active 的槽不被同位重复覆盖、但更高优先级的响应能进来」的逻辑,正是「可打断」需要的判定。不需要为场景单独发明打断机制,复用流水线即可。 返回点连续性也有现成的形状可抄:车辆篇的意图状态(目标车/座/序列号,消费后回填结果)就是「一段可恢复的往返」的样板——场景侧对应一个「场景占用状态」(点句柄/使用样式/序列号),被打断时外壳留着它,威胁解除后按它重进场景;「可恢复」的实现和「上车意图」采用相同结构,原型不需要第二套发明。 - 「生成 vs 第一份行为任务」的分离有对应边界:原型已经把「实体创建」和「实体的初始状态/任务」分在不同的调用点(世界运行时负责创建与登记,实体的初始任务槽是之后设的)——这正对应原版工厂 vs 实体接入点的拆分。场景的「生成后装上场景控制任务」将来接在这条边界上,不会污染创建路径。
- 数据驱动的点存储:规划上,场景点会挂在 UE 的世界分区数据层上做流式,元数据用数据资产承载,让策划配「这类点做什么」。而认领 + 执行复用 Smart Objects。
诚实边界:上面第三条是方向,不是已实现。场景点的持久存储、区流式加载的具体触发时机、聚簇/扩展范围/主动撮合的协调器,原型里都还没写;原版这套流式换页策略我也没做过一比一的对照。这里给的是「基础层已经为场景预留了控制外壳和生成边界」这个事实,加上「用世界分区数据层承载点存储、用 Smart Objects 做认领执行」这个方向——细节当缺口和盲区处理。
三、locomotion 与动画表现:定调

本章篇幅保持简短的依据:任务决定做什么,locomotion 决定怎么移动,Animation 决定怎么表现。本篇只负责明确任务与运动意图的接缝职责,不展开动画混合树内部;那部分属于引擎实现与后续落地篇。
这一章要解决的问题:NPC 走路、跑步、转身的动画,该自建还是复用?行为层和动画层的接缝画在哪?本章篇幅保持简短的依据——短,恰恰是接缝画对了的结果?
先亮结论:这是一个定调章,不是深挖章。 动画表现层的方案已经明确——复用引擎,后置处理——所以本章只讲三件事:原版这层长什么样(结构级)、为什么复用是对的、接缝怎么画。定调并非缺乏依据的暂缓:本篇第四章会看到,物理表演那族任务的出口是一个「从物理混回动画」的专门任务——也就是说,动画层的接口形状(「混入/混出」是显式任务)其实已经被相邻系统定死了一半;剩下那一半(混合树内部)恰好是引擎的强项。「已被邻居定形 + 引擎强项」双重理由,才敢把这一章压成定调。
① 原版机制(结构级)
被物理接管≠任务缺席。 物理表演期间仍有一层行为继续驱动肌肉;本章讨论的是这段交接如何保持任务身份,而不是简单切换一个布娃娃开关。
原版有一个独立的运动系统层:任务层产生「以什么步态往哪动」的运动请求,运动系统把请求变成各物种(人/马/鸟/四足/水中)的具体运动与动画。它和任务层的关系,正是本系列反复出现的「策略与执行分离」:任务不直接摆骨骼,任务下发运动意图;运动系统消费意图、驱动动画。 原版这一族的笔记厚度是 deep 级(二十多篇),各物种的运动状态机、步态切换、转身预测都有细节可挖——但那是后续专篇的题目,本篇只取这一条结构结论:运动意图和动画驱动之间,有一道明确的接缝。「各物种」这个词本身携带一条设计信息:运动系统按物种分套,但任务层不分——「去那边」这个任务对人、狗、鸟是同一个任务,物种差异被整个吸收在运动系统内部;这条「差异止步于接缝」的纪律,正是接缝画对了的证明。
(动画混合树的内部——混合空间怎么算、过渡怎么插值——在上篇就标了盲区,本篇维持:那属于「引擎已解决的问题」,逆向侧也没读。)
这一章的意义:动画层的迁移问题,不是「怎么做动画」(引擎的事),而是「行为怎么正确地不碰动画」——任务下发运动意图、运动系统消费意图,这道接缝画对了,行为层的全部纪律(打断/回退/溯源)就不会被动画细节污染。定调章的产出是这道缝的位置和形状。
② 动画层的引擎复用边界
和车辆刚体物理同理:locomotion 动画是「与人口所有权、任务因果都无关的表现层现成组件」。 UE 的动画栈(Animation Blueprint、Motion Matching、Control Rig、IK)是引擎投入最重的领域之一,自建既费力又难追上。系列心法在这里的应用是:自建的是「行为怎么决定运动意图」,复用的是「运动意图如何转化为骨骼动画」。 选型内部(状态机式 AnimBP 还是 Motion Matching)留到落地时再定——接缝设计对两者是同一个:意图包进、姿态出;这正是先画缝后选件的好处,选型变成可推迟的局部决定。
③ 原型状态与规划
未开始,且刻意后置。 原型当前连「走路」这个行为本身都还没接(第一章),动画自然排在更后。规划上的接缝设计,和车辆篇下篇讲的物理集成接缝对位:
- 行为层产出一个运动意图包(目标点/速度/步态/姿态请求),不直接碰动画——字段草案沿用车辆驾驶指令的组织形状:意图字段 + 来源类型与标签(谁下的意图)+ 就绪判定(缺目标或缺步态即不就绪);「运动意图」对行人,就是「驾驶指令」对车,连仲裁(移动任务和惊吓反应抢运动权)都可以照搬候选-就绪-优先级那套;
- 一道适配器接口把意图交给 UE 侧的表现层(移动组件 + Animation Blueprint / Motion Matching);姿态的回读也走这道缝——任务有时要问「动作播完了没」「脚落地了没」(进出车链等这类信号推进步骤),这些查询做成适配器上的只读接口,行为层依旧不碰动画内部;
- 接缝上配诊断快照,让「行为说要跑、动画却在走」这类接缝 bug 可定位。
这个「意图与表现隔离」的形状,原型已经在车辆物理接缝上验证过一次(真实代码),行人动画接缝将来照此办理——甚至能预写它的验收清单(沿用车辆接缝的验收结构):意图包带就绪判定、默认接一个「什么都不播但如实记录」的空适配器、意图缓冲带修订号、预渲染相位抄诊断快照、配一条「适配器不运行动画」的行为测试。车辆篇把这类接缝的每一步都验证过一遍,行人动画接缝是一次有先例的实施。
诚实边界:以上全部是规划;各物种运动的深挖(步态状态机、转身预测)留给后续专篇。
四、ragdoll 与物理反应:定调


这一章要解决的问题:NPC 被车撞、被爆炸掀翻、从高处摔下时的物理反应,该怎么做?更准确的问题是:「被物理接管的那几秒」在任务系统里是什么身份——是行为的中断,还是行为的一种?这个身份问题决定了打断、联机、脚本编排对那几秒是否生效。
这一章介于定调与深挖之间。 这一块原版证据厚(相关笔记 deep 级、三十来篇),算法内核是明确的盲区,原型侧完全未开始——但结构级的可讲内容远超初稿预期:任务身份、输入维度、升降级阶梯、回动画的桥,全部有具体的任务名与转换条件可考。本章按「深挖结构、盲区内核、规划落地」三档写。
① 原版机制(结构级)
原版的倒地不是纯布娃娃。它用的是行为化 ragdoll(行为化物理一类技术的思路):角色被撞击时,物理接管骨骼,但接管期间角色还在「表演」——伸手护头、试图保持平衡、踉跄几步再倒。玩家能直接感知这个差别:纯布娃娃的 NPC 挨一枪像被抽掉了骨头的布偶,行为化的 NPC 会先挣扎再倒下——「他刚才还是个活人」的错觉,恰恰在被击倒的那半秒里最强烈,这半秒是这套技术的全部意义。也就是说,物理接管 ≠ 行为消失,有一层「物理表演行为」在 ragdoll 期间继续驱动肌肉。这层甚至渗透进普通执行任务:车辆篇讲过的「抓门」中断叶子,最后一步就是「装上平衡辅助、交给自然运动接管」——「交给物理」在原版里是任务链的一个显式出口,不是一个意外。把这个例子放回本章的框架里看:抓门叶子的那一步,就是「进出车链」向「物理表演族」的一次正式移交——任何任务都可以把自己的失败出口指向一个物理表演任务,这比「摔了就切 ragdoll」的全局钩子精细得多:每个任务自己决定哪种失败值得物理接管、接管进哪种表演。
结构级能讲的比初稿以为的多——按母库对「通用受击」一族的函数级笔记,整理出骨架:
其一,「物理表演」不是一个任务,是一族任务。 受击反应(flinch)、分级坠落(fall down)、高处坠落(high fall)、放松(relax)、倒地负伤(injured on ground)、以及母库另有专篇的爆炸/着火/触电、被携带/被拖拽、爬行恢复、从物理状态起身……每种物理表演是任务树上一个正式的受击任务,和「走路」「用场景」平级地占据任务槽——「被物理接管」在这套系统里是一种任务状态,不是任务的缺席。上篇讲的打断/优先级/生命周期,对物理表演任务同样适用。任务化立刻带来两个别处得不到的能力:联机克隆能同步「他正在被撞飞」(物理表演是任务,任务本来就会被序列化——车辆篇讲的克隆机制自动覆盖它);脚本能编排物理(「让他摔下楼梯」是下发一个任务,不是逐个操纵刚体)。
其二,以「受击反应」为例,一个物理表演任务拥有什么。 短受击执行任务(母库确认它是这一族的存活主力)拥有:命中点信息的语境转换、就地重定向(连续挨打不重建任务,原任务原地更新目标)、按武器元数据取调参集、按攻击者近战动作取调参集、护甲/楼梯/致命伤/玩家死亡/持械这些叠加层(叠加的意思是:基础表演不变,按语境往上盖修正——穿护甲晃得轻、在楼梯上另配调参、手里有枪时护枪的姿态混进来;语境修正不产生新表演种类,只修饰既有表演)、以及冲量的四来源缩放(武器、玩家力量、双方相对速度、命中部位)。「挨一下」的表现力,来自输入维度的丰富,不来自表演算法本身——算法内核(平衡控制器怎么算)是盲区,但「喂给它什么」全部可考。「就地重定向」再单看一眼:连击场景里每一拳重建任务,任务的初始化开销与状态丢失都会叠加;原地更新目标,连击就是同一个任务的连续输入——它和车辆篇「追击不断重写 goto 目标」是同一个手法:高频变化走参数更新,不走任务重建。
其三,交接协议有具体的阶梯和出口。 表演中的升降级是显式的:平衡成功 → 转入「从 物理状态混回动画」的专门任务(物理→动画的桥有自己的任务名,不是「哪帧好了就切」);平衡失败 → 附加失败处理消息(楼梯上还有楼梯专用的调参);垂直速度跌破阈值 → 降级进高处坠落任务。「踉跄→倒地→高坠」是一条任务间的显式阶梯,每一级转换都有条件和去向。「混回动画」单独成任务这件事再强调一遍——它意味着「从物理里爬出来」也是一段有生命周期、可被打断、可被观察的过程:混回一半又挨了一枪,打断的是「混回任务」,新的受击任务顶上,状态仍然可追踪;如果混回只是一次切换调用,这个「混到一半」的窗口就是未定义状态窗口。
其四,连「下线一种表演」都有明确流程。 这一族里有一个已退役的「踉跄」任务:实现整体包在条件编译里、构造函数直接断言「此任务已停用」、任务类型枚举被注释、脚本命令入口硬性报错并自动替换成「放松」任务。行为下线不能只删除文件,而应将每个入口改为明确拒绝并提供回退行为——十几年的老工程里,「安全地删」和「安全地加」同样是纪律。为什么不能直接删?因为任务类型是外部可见的契约:老脚本、老存档、网络对端都可能还持有这个类型的引用——每个入口的「断言+兑换成安全的近似行为」,就是让所有历史引用都体面降级的兑换窗口。这和交通篇「GPS 语音编译期关死」是同一类现象的两种处理档:纯内部的通道可以一关了之,上过契约的通道必须开兑换窗口。
至于物理表演内部怎么算(平衡控制器、肌肉驱动),仍是读不到的算法内核,盲区——但如上,盲区被接口包住了:输入维度、升降级阶梯、回动画的桥,全部在盲区之外。
这一章的意义:NPC 的倒地反应,核心不是「接一个 ragdoll」,而是一份行为与物理之间的交接协议——什么时候交、交出去表演什么、什么时候收回来。原版给这份协议的形状是「任务化」:物理接管做成正式任务,打断、优先级、生命周期这些既有纪律自动覆盖物理时段——「被撞飞的 NPC」和「坐长椅的 NPC」在调度器眼里是同一类公民,只是任务不同。协议照结构填空、布娃娃复用引擎、表演内核当盲区,三条边界画清,这一章的迁移就不会跑偏。
② 表现与物理的复用边界
- 物理布娃娃基建复用引擎:UE 的物理资产、Physical Animation、Physics Control 组件,提供「骨骼受物理驱动 + 保留部分动画控制」的基建——这正是行为化 ragdoll 需要的底座。
- 「交接协议」自建,而且现在有原版的具体形状可抄:物理表演做成正式任务(占任务槽、有优先级、可被打断)、升降级做成任务间的显式阶梯(踉跄→倒地→高坠各有条件)、回动画走一个专门的「混回」任务而不是随意切换、「挨打」走上篇的事件裁决链进入。协议的每一段都有原版任务名对应,自建时是照着结构填空,不是发明。
- 输入维度先行:受击表演的丰富度来自输入(武器调参集、叠加层、冲量缩放),这些是数据管线问题——武器表加一列调参引用、命中信息带部位——可以在物理表演本体落地之前先把数据口留好,和交通篇「表现可以晚接、数据口不能晚留」同一条。
- 阶梯的 UE 对应:升降级阶梯落到 UE,大概率是 Physics Control 的配置档切换——「踉跄」「倒地」「高坠」各是一档物理控制参数(哪些骨骼受多强的动画牵引),任务切换时换档;「混回动画」对应把物理牵引权重从 1 平滑走到 0 的一段受管过渡。档位与任务一一对应,阶梯的条件判断留在任务层——物理组件不知道「高坠」这个词,它只认参数档。
- 物理表演的内核(平衡/护头这类「像人」的反应)——盲区 + 后续专篇的题目;第一步可以先用引擎基建做「纯物理 + 简单姿态保护」,行为化表演后补。
③ 原型状态与规划
未开始。 原型的实体连 transform 都还没接到真实物理(车辆篇下篇讲过,物理接缝下游是 null 适配器),ragdoll 排在整个表现层之后。本章的价值是把「交接协议自建、布娃娃基建复用、表演内核当盲区」这三条边界先钉下来,免得将来把「接了一个 ragdoll」误当成「做完了受击反应」。
五、上下两篇合读:行人主题的四条贯穿线
任务身份:坐着、逃跑、掩蔽、ragdoll 都不是渲染层的孤立状态;一切可见状态,在系统里都有任务身份。
惊吓叙事之前,先把行人上下两篇合起来的结构规律收成四条(每条都同时出现在两篇里):
- 裁决与执行隔一层显式路由:上篇的事件桥(事件候选→响应表→任务槽)、本篇的三段式(选择器→包装→执行者)、场景的分发桥(元数据→任务类→外壳)——「决定做」和「怎么做」之间永远隔着一个只做映射的中间层,替换任何一端都不惊动另一端;而且三处路由都是数据表驱动(响应表/场景元数据),内容侧改表就能改行为的路由。
- 生成与行为任务分家:上篇的工厂 vs 实体接入点、本篇的聚簇生成 vs 场景任务装配——「造实体」和「给行为任务」在每个尺度上都是两个 owner。
- 中断-恢复对称:上篇的合法 no-op(有权不反应)、本篇的返回点连续性(反应完回得去)——一进一出配成一对,人群的秩序感来自这个对称。对称的度量也现成:一场骚乱平息后十分钟,街景和骚乱前的相似度——no-op 决定了骚乱波及多少人,连续性决定了波及者回来多少。
- 表现是任务的形态,也是任务状态的一部分:掩蔽是场景任务、被撞飞是 受击任务、走路是移动任务——一切可观察状态在系统里都有任务身份,于是打断、优先级、序列化对一切表现统一生效。这条的反面测试:世界里有没有「可观察、却没有任务身份」的状态?有,就有一块行为逃出了调度器的管辖——那块迟早出对不上账的 bug。
这四条与交通篇收的四条不变式(动静分离/门面消费/准入回流/推导不同步)互不重复、彼此正交——交通那四条管「系统之间」,行人这四条管「一个实体之内」;两组拼起来,就是这个原型对「开放世界运行时」的完整答案的雏形。而且两组各有一条互为镜像:交通的「准入即净化」对行人的「裁决即过滤」(合法 no-op 把不该反应的刺激滤在任务系统之外)——一个把脏东西挡在系统外,一个把噪声挡在行为外,城市的秩序感一半靠这两道滤网。
六、行为链示例:从感知事件到执行状态

收尾前用一段完整的行为串起本篇。选「惊吓」做样本不是随意的——它是唯一一条在几秒内穿过全部四章机制的日常行为链(战斗太长、闲逛太浅),最能检验各章接口是否真的咬合(每个环节括注主讲位置;这描述的是原版机制的协同,原型侧状态见各章③):一个 NPC 在长椅场景点上坐着(第二章:点存储+分发桥造出它,未警觉外壳包着它)——街对面一声枪响,事件进入它的候选队列、被裁决为「被动恐惧」而非「逃跑」(上篇第六章的裁决;它性格胆小但离得远)——聪明逃跑选择器选中「掩蔽」支,掩蔽过渡包装层解析出一个原地反应场景,场景化掩蔽执行者让它蹲下抱头(本篇第一章的三段式;掩蔽的表演走第二章的场景执行模型)——这时一辆失控的车擦过长椅,撞击事件直接把它送进物理表演:受击执行任务按撞击的部位与相对速度取调参、物理接管、它踉跄两步稳住了——平衡成功,「混回动画」任务把它从物理手里接回来(第四章的阶梯与桥)——威胁解除,未警觉外壳凭着保存的返回点,把它送回那张长椅(第二章的连续性)——若长椅这时被别人占了或被脚本圈进了禁区,外壳的重进场景会被正常拒绝,它退回默认游荡:恢复也走一遍完整的准入,没有「凭旧票免检」。几秒钟的街头小事故,四章的机制各管一段,没有一行专门为「枪响+车祸+回座」写的剧本。 原型侧的对照照例交代:这条链上今天真实存在的是上篇的裁决与路由骨架(事件候选、响应表、任务槽、抑制开关),本篇四章的执行侧全部还是规格——这段叙事等价于行人主题的端到端验收剧本,哪一段先落地,就先在这段剧本里点亮哪一句。
对照着想一遍「缺一块会怎样」,更能看清每块的贡献:没有裁决层的合法 no-op,枪响时整条街同步蹲下,出现群体同步反应;没有三段式,掩蔽逻辑长在逃跑任务里,想加「躲进车里」得改逃跑;没有场景连续性,惊吓过后长椅永远空着、NPC 呆立原地;没有物理表演的任务身份,被撞的 NPC 在联机另一端只是凭空倒地;没有混回桥,爬起来的一瞬间骨骼从物理姿势跳到动画第一帧。连续行为表现来自十几个否定条件同时不成立。 这也是验收「活街景」的实用方法:与其盯着「像不像」这种主观题,不如逐条检查否定句——是否存在未释放的场景占用、有没有群体同步反应、有没有呆立原地的惊吓幸存者、联机对端有没有凭空倒地——否定句清单比审美争论更能推进工程。
七、迁移的取舍:行人篇(下)的落地清单
判据沿用系列口径:① 已落地 / ② 已立骨架 / ③ 未开始 / 复用 / 盲区。读这张表建议带着上一节的四条贯穿线:每一行「③ 未开始」的条目,都能在四条线里找到它将来要遵守的那条——比如聚簇遵守「生成与行为任务分家」、返回点遵守「中断-恢复对称」——规格不只是清单,规格之间有宪法。
| 层 | 关键机制 | 原型状态 | 落点 |
|---|---|---|---|
| 任务执行 | 任务槽推进(计数级骨架) | ② 已立骨架 | ProcessIntelligence(上篇详述) |
| 任务执行 | 响应表(事件→树/优先级/任务的映射) | ② 已立骨架 | 响应表状态(选择器骨架) |
| 任务执行 | 外层策略 FSM + 叶子任务 | ③ 未开始 | 规划自建,结构对齐进出车/驾驶栈范式 |
| 任务执行 | 走/逃等具体任务行为 | ③ 未开始 | 执行任务内部复用 UE 寻路/移动 |
| 任务执行 | 被动恐惧三段(选择器/过渡包装层/执行者) | ③ 未开始 | 原版 deep;执行者优先落地 |
| 任务执行 | 掩蔽复用场景执行模型 | ③ 未开始 | 原版 deep;恐惧是内容不是新机制 |
| 场景行为 | 世界预置交互点(数据层) | 复用 | 规划用 Smart Objects |
| 场景行为 | 可打断控制外壳(含返回点连续性) | ② 挂点就绪 | 复用感知流水线的打断逻辑 |
| 场景行为 | 协调器、主动撮合 | ③ 未开始 | 基础层已预留生成边界 |
| 场景行为 | 聚簇(成组生成 FSM) | ③ 未开始 | 原版 deep;与路障同属装配体族 |
| 场景行为 | 封闭区(全局禁区表,存量增量同管) | ③ 未开始 | 原版 deep;纯数据注册表 |
| 场景行为 | 实体覆盖校验(点与流式实体对账) | ③ 未开始 | 原版 deep;流式世界的对账员 |
| 场景行为 | 点存储流式 | ③ 未开始 | 规划挂世界分区数据层 |
| locomotion | 运动意图→动画的接缝 | ③ 未开始 | 规划,与车辆物理接缝相同的结构 |
| locomotion | 动画系统本身 | 复用 | Animation BP / Motion Matching / Control Rig |
| locomotion | 各物种运动内部 | 盲区+专篇 | 原版 deep;本篇只定调 |
| ragdoll | 物理布娃娃基建 | 复用 | 物理资产 / Physics Control |
| ragdoll | 物理表演=正式任务(占槽/可打断) | ③ 未开始 | 原版 deep;交接协议照结构填空 |
| ragdoll | 升降级阶梯(踉跄→倒地→高坠)+ 回动画桥 | ③ 未开始 | 原版 deep;每级转换有条件有去向 |
| ragdoll | 受击输入维度(调参集/叠加层/冲量缩放) | ③ 未开始 | 数据管线先行,数据口先留 |
| ragdoll | 行为化物理表演内核 | 盲区 | 算法内核读不到;被接口包住 |
把两篇的清单合起来,行人主题的建造总排期可以排出来了:感知流水线的行为填充(移动任务)先行 → 环境行为(场景点存储用 Smart Objects + 分发桥 + 外壳连续性)第二 → 响应家族(执行者→包装→选择器,自底向上)第三 → 人口空间策略(钥匙孔/预算/剔除,上篇的③)与场景生态外围(聚簇/封闭区/覆盖校验)并行推进 → 动画接缝与物理表演(依赖表现层桥接)最后。排序的两条依据和交通篇相同:依赖方向(被消费的先做)与消费广度(移动被一切行为消费,所以第一)。上篇立的是「谁调度谁」,本篇排的是「先建哪一块」。 还有一条行人特有的提示:第一个可玩的里程碑不需要响应家族——「街上有人走、有人坐、被枪声惊起又坐回去」只用到移动+场景+事件裁决(裁决在上篇已是骨架);把这个「最小活街景」立起来再长响应家族,每一步都有可观察、可验证的运行时结果。
读这张表的一句话:本篇没有一行「① 已落地」——这是刻意如实的。行人主题的执行与表现侧,原型还没走到;本篇的产出是三条画清楚的接缝(执行任务的编排/现成件分界、运动意图/动画分界、行为/物理交接协议)、两个复用定调(Smart Objects、动画栈),以及这次深挖补上的一批可验收结构(被动恐惧三段、掩蔽走场景、外壳连续性、聚簇/封闭区/覆盖校验三件套、受击任务阶梯与回动画桥)。上篇立的骨架(任务槽、事件桥、打断逻辑)是这一切将来的挂点——地图先于道路,接缝先于填充,这是整个原型一以贯之的节奏。表的行数从初稿的十来行长到二十来行,不是范围膨胀,是同一片领土的地图从省级放大到了县级——每行都能指到母库的一段函数级证据。用这张表的方式也升级了:每行的「落点」栏现在同时是测试命名的词根——将来「聚簇」落地时,测试就叫「簇等待流式依赖」「簇整组despawn」「禁区清退活跃场景」,规格与验收之间不再有翻译层。
行人执行侧的三条通用经验
与前几篇的经验小节对仗,本篇沉淀三条——它们的共同出处是「执行层要跟内容规模纠缠」这个行人特有的处境(几万个点、几十种反应、十几种表演):
其一,新行为优先做成旧机制的内容。 掩蔽没有自己的表演运行时——它是一个场景;恐惧没有专属的打断机制——它走事件裁决;场景里的车不归场景管——它走车辆生成的正规管线。每次想「为 X 新建一套系统」之前,先问「X 能不能是现有系统的一条内容」——这套运行时在行人执行侧几乎每次都采用后者,系统数量因此十年没有爆炸。判断「能不能」的操作化问法是路障那条(交通篇):现有哪个 owner 的生命周期能完整承载它? 掩蔽的生命周期和「用一个场景」完全同形(进入-持续-被打断/完成-退出),所以它是场景;而路障谁都承载不了,所以它配新类。
其二,打断要配连续性,否则打断就是破坏。 干净退出解决「不留脏状态」,返回点解决「可恢复」——两个合起来才是完整的可打断性。连续性还有一个容易漏的第三件:占用要跟着人走——被打断的 NPC 若还占着场景点,点对别人就是死的;外壳在保留返回点的同时,占用的保留/释放策略也要显式定(短打断保留、长打断释放),这正是场景占用状态带序列号的用意。只做前一半的系统,NPC 被惊扰一次就永久丢失原有生活,街道会随时间「熵增」成一群无所事事的游荡者;返回点是对抗这种行为熵增的机制。顺着这条想,「表现力」的另一半藏在输入侧:受击执行任务的四来源冲量缩放(武器、力量、相对速度、部位)说明,同一个表演算法,喂十个维度的输入就有十个维度的差异——先扩输入维度、后换表演算法,是提升「挨打像不像」的性价比顺序;个性计算器(交通篇)用两个标量撑起全城司机的差异,是同一条法则的另一头。
其三,交给物理不等于交出控制。 物理表演是正式任务、有输入维度、有升降级阶梯、有回动画的桥——「ragdoll」在这套系统里是被管理的一段旅程,不是行为系统的尽头。反例是「碰撞即直接切换 ragdoll、瘫倒不动等玩家走远再删」——那是把物理当垃圾桶,而不是当表演媒介。同样的原则平移到任何「交出去」的场合都成立:交给动画(第三章的回读接口)、交给引擎寻路(执行任务内部)、交给 Smart Objects(认领)——每一次移交都保留三样:进入的条件、期间的观测、收回的出口;三样齐了,复用就不是失控。
AI 协作复盘
AI 负责建立规格,人负责决定规格。 这篇最重要的产出不是把原版细节堆得更厚,而是把哪些结构应当成为规格、哪些仍然属于盲区和规划项分开。
这一篇的写作难点和上篇正好相反:上篇的风险是「细节太多讲不清」,本篇的风险是「没有落地代码可讲,容易把规划写成事实」。而深挖之后又叠了第三种风险:原版细节厚了,容易把「原版讲透」误当成「迁移讲透」——所以本篇每段原版深挖的末尾,都尽量落到一条迁移含义(三段式→替换成本、任务化→联机与脚本、退役章法→契约通道的兑换窗口),和车辆篇下篇「细节为迁移决策服务」同一条军规。
AI 帮了什么。 把散在三篇既有素材(上篇、车辆篇上下)里的「策略与执行分离」范式统一点破成任务执行层的通用结构;把场景系统那条「存储/元数据/协调器/分发桥」的所有权链从逆向笔记里对齐;为本篇找跨主题的对应关系(失效场景占用=失效车辆占用、掩蔽=场景、聚簇=装配体、意图包=驾驶指令)——对位不是修辞,它们是「已验证过的实现可以直接复用」的复用清单,六篇文章合起来,这类线有二十多条。这次扩写又回读了三篇函数级笔记(被动恐惧任务族、通用受击任务族、场景聚簇与约束运行时),新收获照例以边界结论为主:聪明逃跑不拥有被动恐惧的执行(只是选择器)、掩蔽的表演走场景系统(恐惧是内容不是新机制)、未警觉外壳只管连续性(不是掩蔽的 owner)、物理表演是正式任务(被物理接管≠任务缺席)、退役任务的下线章法(枚举注释+入口断言+自动回退)。locomotion 一章按用户定调保持轻——但「轻」的依据这次写明了:动画接口的形状已被物理表演的「混回」任务定死一半。
两个被深挖推翻的初稿判断,如实记录。 其一,初稿把 ragdoll 写成「只能定调的章」——回读受击任务笔记后发现结构级内容(任务身份、阶梯、桥、输入维度)足够撑起半章深挖,「定调」升级成「结构深挖+内核盲区」;其二,初稿把场景系统等同于「点+任务+外壳」——聚簇/封闭区/覆盖校验/车生成器这四个世界侧件在初稿里完全没有名字,深挖后才把生态补全。两个误判同根:「原型没做」在初稿里被不自觉地滑成了「没什么可讲」——原型的进度和原版的可考深度是两个独立变量,这次把它们重新解耦了。
哪里要刻意克制。 本篇的原版笔记够写得比现在深得多,但原型侧零代码——写深了,读者会误以为原型也走到了那里。处理方式是:①段放开写(函数级证据都在),③段第一句钉死「未开始」,「惊吓叙事」开头声明讲的是原版协同,迁移取舍表如实呈现「本篇没有一行已落地」。深挖之后本篇的价值主张也更新了:产出从「几条接缝的位置」升级为「一批可验收的结构规格」——接缝告诉你在哪切,规格告诉你切完每一块长什么样;两者都不是代码,但都能直接变成下一步的任务单。另一处克制在措辞:凡写「UE 侧大概率如何」的段落(Physics Control 档位、StateTree 选型),都用了「草案/大概率/留到落地再定」的限定——规划的确定性也要分级,把「已由原版结构决定的」和「到时候再选的」混为一谈,规格就退化成愿望。
证据的可追溯性。 本篇①段的每个新断言都能指回一篇具体的母库笔记与它引用的源文件(被动恐惧一族对应威胁响应/碰撞响应/掩蔽场景三个源文件的消长,受击任务族对应受击/坠落两个任务文件加武器伤害的生产端)——写进文章的每个任务名,都在笔记里有「谁拥有/谁不拥有」的双向结论;没有双向结论的内容(比如具体的恐惧选择阈值)一律没写。
盲区怎么处理。 动画混合树内部、寻路内核、物理表演内核,一律标盲区;各物种运动的深挖标「后续专篇」,在地图上占位但不预支内容。这次深挖还实践了一遍「盲区被接口包住」:物理表演的内核照旧读不到,但它的输入维度(四来源冲量缩放、叠加层)、转换条件(平衡成败、垂速阈值)、出口(混回任务)全部从消费端与调用端核对确凿——围着黑盒把针脚数清,黑盒就成了可替换的元件;将来在 UE 里给这个「元件位」装一个自研的简化表演器,接口即验收。
*这是「如何制作一款开放世界游戏」系列实战篇。行人主题按层切成上下两篇:上篇讲调度与决策(基础层、表示、人口、LOD、感知流水线),本篇(下)讲行为、表现与物理(任务执行与响应家族、场景生态五件套、locomotion 定调、ragdoll 的任务化交接协议)。本篇①段对照被动恐惧、受击任务、场景运行时三线函数级逆向笔记;原型侧如实呈现:执行与表现侧尚未动工,产出是接缝设计、复用定调与一批可验收的结构规格。文中所有类名与源码路径均为长期逆向阅读与在建工程的实地核对结果,发布时按惯例做匿名化处理。*