船只创建
1. 简介
1.1. 文档目的
本文档是一份全面、端到端的指南,用于在游戏中创建并集成自定义船只。它是为想要向 Bannerlord 的海战系统添加完全可用船只的模组作者而编写的。你不需要是程序员也能跟随本指南,但你应当熟悉在 Bannerlord 编辑器中进行操作,并理解实体(entity)、预制体(prefab)和脚本的基本概念。
本指南的目标是带你走完整个技术流程——从建立最初的嵌套预制体(Nested Prefab)层级结构,一直到最终的游戏内实现。按照这里概述的工作流程操作后,你将制作出一艘与游戏的物理系统、AI 导航、登船、船员交互和升级系统完全兼容的船只。
1.2. 船只创建流程概览
船只创建过程遵循一个结构化、分层的工作流程。每一层都依赖于前一层,因此不要跳过步骤非常重要。整个流程从建立正确的嵌套预制体层级结构开始——这是其他所有系统所依赖的骨架。
工作流程分为三个主要阶段:
- 核心设置(必需): 建立根实体、导入船体网格,并配置物理体积(碰撞体和浮力体),以确保船只能够存在并在物理引擎中正确漂浮。在完成此阶段之前,其他任何内容都无法正常工作。
- 玩法集成(升级): 实现导航系统(舵、帆、桨)、登船机制、弩炮以及玩家控制和战斗所需的交互点。这些组件定义了玩家和 AI 与船只的交互方式。
- 细节与润色(装饰性): 通过视觉升级、粒子效果、水面交互和装饰元素来完善船只,以增强氛围感。这些组件纯属视觉效果——移除它们不会破坏船只的功能。
2. 船只层级结构与组件分解
在本节中,船只组件被分为三个主要组:必需组件(对玩法至关重要)、升级组件(玩法功能)和装饰组件(视觉细节)。
在构建船只时,完整的实体层级结构应遵循以下通用结构:
[ShipName]_ship_nested (根实体) ├── mesh_holder ├── floater_volume_holder ├── control_point_holder ├── climbers_holder ├── attachment_machine_holder ├── barrier_holder ├── spawn_point_holder ├── rudders_holder ├── hull_group ├── shields_group ├── oars_holder ├── sail_holder ├── ship_ballista_holder ├── wetness_decals ├── ship_water_effects (仅视觉) ├── ship_burning_system └── [其他装饰性容器]
下面各节将详细描述每个子项。在工作过程中请牢记这个层级结构——将组件放在错误的父节点下是最常见的错误来源之一。
2.1. 必需组件(关键)
该组中的对象代表了船只存在于游戏世界、物理功能正常运行以及执行基本操作所需的最低限度配置。如果缺少或错误配置了其中任何一个组件,船只要么无法加载,要么无法漂浮,要么在游戏中行为异常。
2.1.1. 根实体设置(dromon_ship_nested)
此实体是整个船只预制体的父容器。本指南中的所有其他组件都作为此实体的子项或后代放置。在本文档中,我们将使用”Dromon”船作为参考示例。
- 命名约定: 我们建议使用 [ShipName]_ship_nested 格式(例如 dromon_ship_nested)。虽然引擎并未严格强制执行此约定,但遵循它可以确保你的船只易于识别,并与游戏中现有的船只资产保持一致。
所需设置与属性:
预制体设置:
- 启用嵌套预制体(Enable Nested Prefab): [已勾选]
- 原因: 这对于流程管理至关重要。启用嵌套预制体允许层级结构中的子预制体(帆、登船机、桨等)独立打开和编辑,而无需打开整艘船。如果不这样做,编辑任何子组件都会修改整个船只文件,使迭代工作变得缓慢且容易出错。
- 启用将子项写入单独的 XML(Enable Write Children to Separate XMLs): [已勾选]
- 原因: 这确保每个子预制体将其数据保存到自己的 XML 文件中,而不是将所有内容嵌入到一个大文件中。这对于版本控制以及保持船只模块化非常重要——对一个组件的更改不会有损坏船只其余数据的风险。
变换(Transform)与工作空间:
- 恒等变换(Identity Transform): 确保根实体是在通用的恒等坐标下创建的(位置(Pos): 0,0,0 | 旋转(Rot): 0,0,0 | 缩放(Scale): 1,1,1)。
- 原因: 整艘船在运行时由游戏的海战物理系统进行定位和旋转。如果根实体内置了任何偏移或旋转,船只在游戏中将显得错位,所有子组件也会随之偏移。
- 局部空间(Local Space): 对于所有后续的子组件,使用局部变换(Local Transform)执行所有定位和旋转操作。
- 原因: 子实体继承其父级的世界变换。使用局部空间可以确保当根实体移动时(在游戏过程中会持续移动),所有子项都能随之正确移动。使用世界空间会导致子项在编辑器中的位置正确,但在游戏中漂移到不正确的位置。
物理配置:
- 物理形状(Physics Shape): 分配一个大致包裹整个船体的凸形(Convex)物理形状。
- 原因: 这个凸形有两个关键作用。首先,它是船只的主要碰撞体——决定了船只在世界中物理上会碰到什么。其次,对船只来说更重要的是,它是浮力系统的主要驱动因素。游戏引擎会计算这个凸形体积有多少部分被淹没,以此确定向上的浮力。如果这个形状太大,船只会漂浮得过高。如果太小,船只会坐得过低或下沉。请始终使用紧贴水线以下船体外部的网格。
- 注意: 如果提供的网格不是凸形,引擎会尝试自动近似计算一个凸包,但这种近似可能与船体不太匹配。强烈建议提供一个合适的凸形网格。
- 材质(Material): 分配 wood_ship 物理材质。
- 原因: wood_ship 材质定义了船只物理体对碰撞的响应方式——其摩擦力、恢复系数(弹性)和伤害阈值。使用错误的材质(或不使用任何材质)会导致船只在与地形、其他船只或抛射物碰撞时行为异常。
- 质量(Mass): 输入船只正确的物理重量。
- 警告: 此值直接影响船只的漂浮方式以及对水体物理的反应。过轻的船只会在波浪上不规则地弹跳。过重的船只会在水中坐得过低或完全下沉。请使用现有船只作为参考,根据其尺寸确定合适的质量值。
- 刚体标志(Body Flags): 确保以下标志已被勾选:
- ✅ 动态(Dynamic) —— 允许物理引擎根据受力移动此刚体。
- ✅ 可移动(Movable) —— 运动学系统所需,用于同步船只运动与乘客及搭载物体。
- ✅ 使用凸包(Use Convex Hull) —— 告知物理引擎使用凸形形状进行碰撞。
- ✅ 不与摄像机碰撞(Do Not Collide with Camera) —— 防止摄像机被船只的物理体阻挡。
- ✅ 不与射线检测碰撞(Do Not Collide with Ray Cast) —— 防止游戏玩法射线检测(例如瞄准)被船体物理体阻挡。

重要: 添加到此根实体的子实体上的任何物理体也必须在其标志中标记为可移动(Movable)。这是必需的,因为根实体使用的是运动学物理系统——未标记为可移动的子物理体不会随船只移动,而会脱离到错误的世界位置。
2.1.2. 脚本
以下脚本必须直接添加到根实体上。添加它们的顺序无关紧要,但所有脚本都必须存在,船只才能正常运作。
- MissionShip: 核心脚本,将此实体注册为游戏任务系统中的一艘船。没有这个脚本,游戏将无法识别该实体是一艘船,所有海战玩法系统都不会被激活。
- 重要: 你必须将 NavMesh 名称分配给 NavMeshPrefabName 字段。NavMesh 是一个单独的资产,定义了 AI 代理可以在你的船只甲板上行走的位置。NavMesh 烘焙(baking)将在 attachment_machine_holder 一节(2.1.7)中详细介绍。
- Volume_generator: 处理浮力系统用来保持船只在水面上直立和稳定所使用的浮动体积对象的生成。
- 最佳实践: 在 mesh_holder 中添加船体网格之后执行此步骤,因为生成器需要该网格来估算正确的体积放置位置。
- 启用 Mock Generation(模拟生成),以便在提交之前预览浮子的放置位置。
- 目标: 通过调整 Current Volume Count(当前体积数量) 或 Floater Volume Width(浮子体积宽度),将可浮动对象的数量保持在最低限度。更多的体积会带来更稳定的漂浮效果,但会消耗更多性能。
- 确保生成的体积尽可能贴合船体形状。
- 点击 Generate Volumes(生成体积),在 floater_volume_holder 下创建体积子项。
- ShipFloatsamManager: 处理船只被摧毁时碎片和漂浮物的生成与行为。确保船只沉没后,破碎的木板、木桶和其他物体会出现在水面上。
- ShipClothFixer: 管理船上的布料模拟系统(主要是帆和旗帜)。如果没有这个脚本,船只移动时船上的布料对象可能会出现异常行为,或根本不进行模拟。
- ShipColorAssigner: 控制船只上基于阵营的颜色着色。
- Factor Color(阵营颜色): 应用于座椅和桨等升级部件,将它们染成所属阵营的颜色。
- Ram Debris Color(撞角碎片颜色): 应用于船只撞击另一艘船时出现的碰撞伤害贴花。
- EditorShipPhysics: 一个仅在编辑器内使用的实用脚本。它能让你在不启动游戏的情况下模拟和预览船只的漂浮物理效果,从而节省大量迭代时间。
- NavalPhysics: 处理运行时的核心游泳和浮力逻辑。此脚本与浮子体积共同作用,以保持船只在水面上正确定向和移动。
- EditorShipUpgradeViewer: 一个编辑器实用工具,可让你在不启动游戏的情况下预览不同升级部件(帆、盾牌、船首像等)在船上的外观。
- ShipAttachmentMachineConnectionLogic: 处理登船期间船只之间的连接逻辑。它管理登船跳板的状态——检测两艘船何时足够接近、触发跳板展开动画,并连接两艘船的 NavMesh。
2.1.3. mesh_holder
该实体包含船只的主要视觉网格以及所有属于船只结构一部分的静态物理对象——平台、楼梯、内部装饰以及任何不会根据升级而变化的其他几何体。
- 变换: 必须保持为恒等状态(0,0,0 | 0,0,0 | 1,1,1)。mesh_holder 不应相对于根实体有任何偏移。单个网格的所有定位都应在该容器内的子实体上完成。
- 物理: 添加到 mesh_holder 子项的任何物理体都必须启用可移动(Movable)标志。原因见 2.1.1 节中的说明。

主船体网格所需的标签:
- rope_physics_body —— 将此实体标记为船上动态绳索模拟(索具、系绳等)的物理锚点。附着在船上的绳索使用该标记实体作为其根附着点。
- body_mesh —— 将此实体标识为主要的视觉船体。多个引擎系统(包括 ShipWaterEffects)使用此标签对船体执行射线检测,以自动计算粒子位置、水线高度和其他视觉参数。此标签必须存在,且该实体必须具有带有准确包围盒的有效 MetaMesh。
- hull_water_mesh —— 标记专门用于船体内部水体模拟系统的网格。该网格定义了模拟甲板积水所渲染的视觉内部表面。
甲板积水(Deckwater)设置: 在 mesh_holder 内创建一个名为 deckwater 的子对象,并为其分配 render_to_depth 标签。
- 原因: render_to_depth 标签告诉船只水效果系统将此网格包含在用于定义甲板上模拟水体可以积聚位置的俯视深度渲染中。任何带有此标签的网格(包括桨座和其他甲板家具)都会对深度纹理做出贡献。添加或修改 render_to_depth 网格后,请在 ShipWaterEffects 脚本中点击 Re-render Depth Texture(重新渲染深度纹理) 以更新模拟。
2.1.4. floater_volume_holder
该实体是根实体上 Volume_generator 脚本自动创建的浮力体积对象的容器。你不应在此手动创建或修改子项——始终使用生成器。
- 验证: 生成体积后,在编辑器中直观检查它们,以确认它们正确覆盖了船体的淹没部分。延伸到水线以上太远的体积会使船只显得异常地高。没有深入船体足够远的体积会导致不稳定。

- 可见性: 一旦验证了体积,就在实体检查器(Entity Inspector)中禁用此实体的可见性。这些体积对象纯粹是功能性的,在正常编辑期间不应可见,因为它们会使视口变得杂乱。
2.1.5. control_point_holder
该实体包含船只的转向机制。此处使用的转向预制体类型取决于船只的物理设计。
- ShipControl_nested: 用于高大的船只,或者舵在物理上无法触及水面的船只,或者转向不是由可见的世界内舵来执行的船只(即转向是抽象的)。此预制体处理转向逻辑,而不需要物理舵网格交互。
- ShipControlRudder_nested: 用于较低矮的船只,其舵在物理上延伸入水中,并由一个代理手动操作。这是更具物理沉浸感的选项。
- 配置: 将舵网格和物理体作为 metamesh 分配给控制器的子实体。舵的物理形状应紧密匹配其视觉网格,因为代理会与其进行物理交互。
2.1.6. climbers_holder
该实体包含允许代理(AI 和玩家均可)从水面爬上船只甲板的预制体。这对于代理游到船边的登船序列是必不可少的。
根据船只栏杆高出水面的高度,使用预制体:longboat_rope_climber_small_nested、longboat_rope_climber_medium_nested 或 longboat_rope_climber_large_nested。
每个攀爬预制体包含三个关键子实体:
- climb_point —— 代理完成攀爬动画后落脚的甲板位置。将其放置在甲板表面,位于栏杆内侧。
- end_position —— 攀爬动画的顶部。应位于栏杆高度处或略高于栏杆。
- standing_point —— 攀爬动画的底部,位于水面处。这是代理开始攀爬的位置。你可以通过该实体上的脚本调整精确的起始位置。
原因: 如果没有正确放置攀爬点,最终落水在船附近的代理将无法重新登船,从而破坏登船玩法循环。
2.1.7. attachment_machine_holder(登船系统)
本节包含登船机制所需的预制体。这是船只设置中较为复杂的部分之一。主要有两种预制体类型:
- attachment_machine_nested: 包含进出双向登船所需的所有实体——即处理我方船只登上敌船以及敌船登上我方船只两种情况。
- attachment_point_machine_nested: 仅包含敌船登上我方船只(登船动作的接收方)所需的实体。

a) attachment_machine_nested 结构:
- distance_helper: 编辑器中的一个可视化实体,显示在跳板可以展开之前两艘船之间所需的最小距离。这可以防止跳板相互重叠或穿透几何体。
- attachment_machine(父级):
- hook: 代理发起登船时投掷的抓钩的视觉表现。这应该是一个放置在钩子静止位置的小网格。
- pilot: 一个非物理实体,放置在甲板上,正位于登船跳板 NavMesh 连接应开始的位置之上。游戏使用该实体的位置将跳板的 NavMesh 与船只甲板的 NavMesh 缝合起来。参见下方的 NavMesh 配置部分。
- focus_object: 代理投掷抓钩时必须命中的物理对象,以使登船尝试成功。将其放置在船只栏杆上,钩子实际会钩住的位置。
- pile_holder: 包含登船设置中可视绳索和悬挂元素的父实体。这些纯粹是视觉性的——它们没有物理或交互功能。
b) attachment_point_machine_nested 结构:
- hook_attach_point: 一个非物理实体,指示敌方的抓钩成功投掷后落在我方栏杆上的位置。将其放置在栏杆表面上。
- pilot: 一个非物理实体,下方需要有一个 NavMesh 面以供跳板 NavMesh 连接。功能与 attachment_machine_nested 中的 pilot 相同。
- visual(父级):
- bridge_target_point: 敌方成功架设跳板后出现在栏杆和甲板上的非物理视觉对象的父节点。默认可见性应为关闭——游戏会在建立跳板时激活它们。
- bridge_connection_point: 定义登船跳板的起点或终点。必须精确放置在栏杆上,确保它没有埋入栏杆的物理网格内部。如果该点位于几何体内部,跳板会发生错误的穿模。
- bridge_source_point: 钩子成功钩中且跳板开始展开后出现的非物理视觉对象的父节点。默认可见性应为关闭。
- focus_object: 敌船成功投掷抓钩所必须命中的物理对象。
- capsule_physics_a: 一个物理胶囊体,允许代理在跳板激活时从甲板爬到栏杆高度。当没有跳板时,该对象处于非激活状态——如果在没有跳板的情况下激活它,会让代理走出船只、悬空在空中。
- 对齐要求: 该胶囊体的顶部必须精确对齐到 bridge_connection_point。
- 自动对齐: 你可以通过启用物理可视化来手动放置它,或者使用根实体 Volume_generator 脚本中的 Auto Arrange Bridge Ramp Physics(自动排列跳板斜坡物理体) 按钮一次性自动对齐所有胶囊物理对象。

- _barrier_ai_04x04m_nested: 一个 AI 屏障,当没有跳板时,防止代理在登船连接点处走出船外。当跳板建立后,该屏障会自动失效,允许代理通过。
c) NavMesh 配置与烘焙: NavMesh 定义了 AI 代理可以在船只甲板上行走的位置。必须正确烘焙它,登船跳板才能正常工作。跳板系统在运行时动态连接两艘船的 NavMesh,下面的 ID 就是它用来识别要连接哪个面的方式。
- 唯一 ID: 在 ShipAttachmentPointMachine 脚本中(两种机器预制体中均有),找到 RelatedShipNavmeshOffset 字段。为每台机器输入一个唯一的整数 ID。同一艘船上的两台机器不应共享相同的 ID。
- 面 ID: 在船只的 NavMesh 中,位于每台机器 pilot 实体正下方的面必须具有与在 RelatedShipNavmeshOffset 中输入的相同 ID。游戏使用这个匹配的 ID 来识别哪个 NavMesh 面是每个跳板的连接点。
- 普通甲板: 船只甲板上所有非跳板连接点的其他 NavMesh 面都应分配 ID 0。
烘焙与保存:
- 选择所有 NavMesh 面。
- 转到根实体上的 MissionShip 脚本。
- 点击 SaveNavMeshFromLocal。
- 输入文件名,并将其保存到你的模组模块文件夹中。
- 将此文件名输入到 MissionShip 脚本的 NavMeshPrefabName 字段中。

2.1.8. barrier_holder
该实体包含物理屏障对象,防止 AI 代理走出船只边缘或进入不应到达的区域(甲板下开口、船首斜桅末端等)。
使用预制体:_barrier_ai_04x04m_nested 或 _barrier_ai_04x08m_nested。它们在功能上是相同的——唯一的区别在于默认尺寸。根据需要缩放以覆盖该区域。
原因: 如果没有屏障,AI 的 NavMesh 系统可能会生成导致代理走出船只边缘的有效路径。屏障会创建 NavMesh 系统所遵守的无形墙壁,从而将代理保持在甲板上。
2.1.9. ship_target_point
该实体持有 ShipTargetMissionObject 脚本,必须存在于每艘船上。它将船只注册为游戏战斗系统中的可被瞄准对象——没有它,诸如弩炮之类的远程武器将无法锁定该船只。
其功能:
- 将船只标记为远程武器的有效目标(TargetFlags.IsShip | TargetFlags.IsMoving)。
- 报告船只当前的速度,以便抛射物能够正确地对移动中的船只进行提前量瞄准。
- 提供一个目标优先级数值,该数值根据船只剩余的船员数量和船体耐久度进行缩放。严重受损或几乎没有船员的船只会自动变为较低优先级的目标。
- 当船只正在下沉时,会添加 NotAThreat 标志,使 AI 远程单位停止瞄准它,并将火力转移到其他地方。
设置: 将 ship_target_point 嵌套预制体添加为船只根节点的直接子项。不需要额外配置——该脚本会通过根实体上的 MissionShip 脚本在运行时自动读取船只的状态。
2.1.10. kinematic_batch_entity
kinematic_batch_entity 系统处理船只的物理优化。如果没有它,船上每个带有物理体的子实体都会被单独模拟,这很快就会变得昂贵。该系统将所有这些物理形状合并为一个随船只根节点移动的单一批处理体——而成本只是一小部分。
工作原理: 船只根节点拥有主要的物理体(凸包)。子实体上所有详细的碰撞形状——船体木板、甲板表面、结构部件——都需要随船只移动,但不需要各自进行模拟。kinematic_batch_entity 将这些全部收集到两个批处理容器中:
- simulated —— 批处理用于完整物理交互的形状(碰撞响应、代理在甲板上行走等)
- ray_cast —— 批处理仅用于射线检测的形状(瞄准、视线检测等)
所需设置: 将 kinematic_batch_entity 嵌套预制体直接添加到船只根节点下。查找方法:在 Modding Toolkit 中打开预制体窗口,搜索 kinematic_batch_entity,然后将其拖放到船只根实体上。
放置后,在实体检查器中验证以下内容:
- 其变换为恒等状态(位置 0,0,0——无旋转,无缩放偏移)。
- 其刚体标志包含 Moveable。
- 它带有 batched_physics_entity 标签。
- simulated 和 ray_cast 两个子项都必须存在。如果缺少任意一个,引擎将发出警告。
标记要批处理的实体: 对于其物理形状应合并到批处理中的每个子实体,在其物理属性中启用 Move To Batched Kinematic(移至批处理运动学) 选项。
在该实体的物理(Physics)面板中:
- 分配一个物理形状(一个 bo_ 体)。
- 启用 Moveable 刚体标志。
- 启用 Move To Batched Kinematic。
应批处理的内容: 船体网格、甲板结构、桅杆座、船体铺板变体、固定的结构几何体。 不应批处理的内容: 船只根节点本身、kinematic_batch_entity 及其子项、AI 屏障实体、绳索/布料物理,以及任何在运行时独立动画或脱离的实体。 升级变体: 如果你的船只在某个升级槽下有多个船体变体,每个变体都可以启用 Move To Batched Kinematic。引擎只会包含船只初始化时处于激活状态的形状——确保每个槽位在启动时只有一个变体处于激活状态。
常见验证错误:
- 未找到标记为 batched_physics_entity 的实体 → “Ship Prefab must contain a root batched physics entity!”(船只预制体必须包含一个根批处理物理实体!)
- kinematic_batch_entity 没有恒等变换 → “Batched physics entity should have identity matrix frame!”(批处理物理实体应具有恒等矩阵坐标系!)
- 缺少 simulated 或 ray_cast 子项 → “Ships should have a ‘kinematics’/‘raycast’ batch entity!”(船只应具有一个 ‘kinematics’/‘raycast’ 批处理实体!)
如果出现上述任何警告,则表示物理批处理未正常工作,船只可能存在性能问题或碰撞缺失。
2.1.11. spawn_point_holder
该实体定义了船只上玩家和 AI 部队的所有生成位置。游戏的任务系统会读取这些点,以确定在海战开始时将代理放置在何处。
- sp_troop_inner_deck_nested: 内甲板部队的生成点——代理被放置在远离船只边缘的位置,通常位于中央或甲板下方。
- sp_troop_outer_deck_nested: 外甲板部队的生成点——代理被放置在靠近栏杆和边缘的位置,例如弓箭手和水手。
- sp_troop_captain_nested: 船长的生成点。
- sp_troop_crew_spawn_nested: 用于战斗期间到达的增援部队的生成点。
rally_point(集合点): 创建一个空实体,并将其放置在船首,位于 NavMesh 表面上。
- 为该实体分配 rally_point 标签。
- 将该实体重命名为 rally_point 以便清晰识别。
- 原因: 这是 AI 代理在收到集合命令时前往的集合点。如果没有集合点,AI 代理将没有明确的集合位置,在被命令重新集结时可能行为异常。
2.1.12. rudders_holder
该实体为游泳和浮力物理计算定义舵的位置——具体来说,它告诉物理系统船只的转向阻力在水中的施加位置。
- 放置: 将此实体放置在船只的最尾部,尽可能靠近水面。
- 设置: 添加一个空实体作为子项,将其命名为 rudder_stock,并为其分配 rudder_stock 标签。
- 原因: 物理系统使用 rudder_stock 标签来定位船只的转向点。如果放置不正确(太靠前或太高),会导致船只的操控表现不真实——它可能转向过快、过慢,或围绕错误的点旋转。
2.1.13.oars_holder
该容器包含船只的桨系统。桨是一种玩法升级——它们决定了船只在无风情况下航行的速度。oar_deck 预制体同时处理视觉上的桨网格和划桨手的坐姿系统。
- 根设置:在恒等位置创建一个空实体,并将其命名为 oars_holder。
- 添加 oar_deck 预制体作为子项。根据其类型重命名:
- oar_deck_upper: 划桨手坐在开放甲板上,玩家可见。
- oar_deck_lower: 划桨手坐在船体内部,不直接可见。
a) oar_deck_upper(可见划桨手):

- 配置: 选择 oar_deck_upper 实体,并在 ShipOarDeck 脚本中点击 ManageOarMachines。
- 初始设置: 首次创建时不要勾选 Override Prefabs(覆盖预制体)。
- 预制体集: 选择与你船只尺寸匹配的预制体集(UpperDeck 4m、6m 或 8m——该数字指的是桨位之间的间距)。
- 定位: 使用 Count(数量)、Span(跨距) 和 Offset(偏移) 值将桨位与船体对齐。这需要反复迭代——调整数值,点击应用,然后直观地验证位置。桨尖应干净利落地入水,手柄应自然地握在代理的手中。
- 座椅高度(关键): 在定位之后使用 Adjust Seat Heights(调整座椅高度) 功能。这是强制性的。划桨动画是固定的,座椅必须处于正确的高度才能与动画对齐长凳。如果座椅高度不对,划桨手在视觉上会穿模或悬浮在座椅上方。

- 角度: 调整桨的激活(入水)和收起(抬起)角度,以匹配你的船体几何形状。
- 镜像: 一旦一侧配置正确,使用 Mirror(镜像) 功能将所有设置复制到另一侧。
b) oar_deck_lower(内部划桨手):
- 设置: 遵循与 oar_deck_upper 相同的流程,但选择 Lower Deck(下层甲板) 预制体集。
- 下层甲板划桨手不需要调整座椅高度。
- 确保桨与船体网格上的桨口对齐,并干净利落地穿出。错位的桨会在视觉上穿透船体。
- 收起状态: 确保收起的桨角度将桨完全置于船体内部。收起时伸出的桨会穿透船体,看起来不正确。*
c) 升级系统集成:
- 桨被游戏的升级系统视为升级部件。
- 可以通过编辑 ship_upgrade_pieces.xml 和 ship_slots.xml 文件,参考现有的桨条目来创建不同的桨套装(铜制桨尖、火硬化桨等)。
- 添加新的桨类型时,请验证预制体层级结构是否与现有类型匹配,否则升级系统将无法识别新部件。
2.1.14. sail_holder(War Sails 帆系统)
帆是船只中技术上最复杂的组件之一。它们结合使用骨骼动画、混合形变(blend shape)和实时布料模拟,以实现在风中逼真的表现。开始帆的设置之前,请仔细阅读本节。
有两种帆类型:方形帆(Square)(悬挂在帆桁上的矩形帆)和三角帆(Lateen)(安装在倾斜桁杆上的三角形帆)。每种类型都有三种尺寸变体(小、中、大),总共形成六种帆预制体。
a) 资产准备:
- 布料模拟网格: 用于布料模拟的帆网格在其默认(完全展开)状态下必须符合 15m × 15m × 15m 的尺寸限制。预制体实体可以在游戏中进行缩放,但源网格必须保持在此限制范围内。
- 拓扑结构: 网格的多边形密度和边缘流向控制着布料的变形方式。在应该鼓起的区域使用更密集的拓扑结构,将产生更精细的布料运动效果。
顶点约束(关键——使用顶点颜色通道):
- Alpha 通道 = 0: 不得移动的顶点(附着在桅杆或帆桁上的顶点)。如果没有这个设置,帆会在模拟过程中从其挂载点上脱离。
- 红色通道 = 0: 连接到左侧控制骨骼的顶点。
- 绿色通道 = 0: 连接到右侧控制骨骼的顶点。
- 蓝色通道 = 0: 位于缝合区域(接缝)的顶点。这些区域模拟各面料板之间的张力。
- 在游戏中: 在布料设置中启用 Create Stitching Constraints(创建缝合约束),以使缝合效果生效。
b) 索具与骨骼:
- 骨骼驱动着调整帆张力和帆桁角度的控制骨。
- 方形帆: 使用 2 个控制骨(帆桁两端各一个)。
- 三角帆: 使用 1 个控制骨(桁杆尖端)。
- 骨骼名称必须与参考层级结构图中显示的名称完全匹配,即使骨骼对象本身有不同的名称。
c) 动画与状态:
- 变形动画(Morph Animation): 需要一个 200 帧的变形动画,表示帆从完全展开到完全收拢的过渡。同样的变形会反向播放以用于展开动画。这个动画驱动着玩家在下达收帆指令时看到的收帆和展帆序列。
- 收拢状态: 完全收拢后,布料网格会被替换为代表捆扎好的帆的静态网格。在此状态下,布料模拟处于非激活状态。
- 燃烧状态: 如果帆着火,它会转变为模拟撕裂、燃烧中的帆的自由悬挂网格。此网格不需要骨骼或变形关键帧——它纯粹是没有控制的视觉布料。
d) 预制体设置(以 sail_square_medium_nested 为例):
将 sail_visual 脚本添加到帆预制体的最顶层父节点,并选择与你的帆变体匹配的正确 sail_type 枚举值。
主要子项:
- pulley_systems_holder: 包含所有绳索视觉系统。
- stability_ropes: 连接控制骨到甲板的绳索(支索和护桅索)。每根绳索实体的标签必须与其所连接的骨骼名称相匹配。
- static_ropes_parent: 静态装饰性绳索。为连接到帆桁的绳索使用 attached_to_yard 标签;为从帆桁延伸至船体的绳索使用 big_rope 标签。
- sail_fold_pulley_parent: 收帆时聚拢帆面的绳索。为每根绳索实体标记其所受控制的骨骼名称。
- sail_rotate_pulley_parent: 负责旋转帆桁以迎风的绳索。
- force_center_entity: 必须带有 force_center_entity 标签。定义了风力在物理计算中施加到帆上的点。将其定位在帆表面积的中心。
- sail_mast: 将所有桅杆视觉网格实体放置在此子项下。
- yaw_rotation_entity: 必须带有 yaw_rotation_entity 标签。将你准备好的帆和帆桁资产放置在此实体下。该实体会旋转以模拟帆桁转向迎风。
- sail_upgrade_slot: 用于帆级升级的升级槽实体。
2.2. 升级与玩法组件
这些组件扩展了船只的能力,定义了其战斗容量,或根据船只的升级等级改变外观和属性。从某种意义上说它们是可选的——没有它们船只仍能存在并漂浮,但没有它们任何海战玩法(航行、战斗、升级)都无法正常运作。
升级系统由若干个 XML 文件驱动,你必须编辑这些文件才能将你的船只及其升级部件注册到游戏中:
- ship_slots.xml: 定义船只可用的所有升级槽类型。你的船只使用的每种升级部件类型都必须在此有对应的条目。该文件中定义的 ID 会被下面的其他 XML 引用。
- ship_upgrade_pieces.xml: 定义各个升级部件——它们的属性、视觉效果、描述,以及它们所属的槽位 ID。
- mission_ships.xml: 将你的船只注册为任务中可用的船只。包含船只的 ID、预制体名称、质量和其他任务级属性。
- ship_hulls.xml: 定义船只的任务统计数据(生命值、速度、机动性等),并指定该船体类型上可用的升级槽。
2.2.1. hull_group
该嵌套预制体控制船只在不同升级等级下船体的视觉外观。
- 放置: 将 hull_group 嵌套预制体添加到船只根实体的恒等位置(0,0,0)。
- 结构: 该预制体包含 5 个子实体,分别对应不同的船体材质或升级等级。
- 设置: 将你准备好的船体网格作为 MetaMesh 添加到对应正确材质名称的子实体中。
- 标签: 升级系统识别船体状态所需的标签已预定义在预制体的子项上。如果你正在创建一种新的船体类型,可以从 XML 中复制现有的船体升级标签,或移除与你的船只无关的标签。
2.2.2. shields_group
该嵌套预制体沿船只的栏杆添加盾牌装饰,这些装饰同时也能保护甲板上的部队免受来袭远程攻击。
- 放置: 将 shields_holder 嵌套预制体添加到船只根实体的恒等位置(0,0,0)。
- 自定义: 可以通过编辑相关的船只 XML,或更改子实体上的 MetaMesh,来增加或减少显示的盾牌数量。
- 阵营颜色(至关重要): 每个盾牌子实体都带有 banner_with_faction_color 标签。正是这个标签使得游戏在运行时将所属阵营的徽记和颜色应用到盾牌上。
- 重要: 你还必须在资源浏览器(Resource Browser)中将 banner_with_faction_color 标签分配给 MetaMesh 资产本身以及其所有 LOD 变体。如果标签只在实体上而不在网格资产上,阵营颜色将不会显示。
2.2.3. cam_holder_nested
该预制体确保船只升级部件在玩家购买和预览升级的城市港口 UI 中正确显示。
- 放置: 将 cam_holder_nested 预制体添加到船只的恒等位置。最佳实践是在放置完所有升级部件之后再添加此预制体,这样摄像机就能被定位到看到完整船只的位置。
- 设置: 该容器为每种升级部件类型包含一个子实体,通过 UI 系统读取的标签进行关联。移动每个子实体以将其定位在船上对应的升级部件之上。
- 摄像机实例: 将 Camera_Instance 子项移动到一个能够以讨喜的角度宽广、清晰地展示整艘船的位置。
- 提示: 将你的编辑器视口设置为所需的摄像机角度,然后右键单击 Camera_Instance 并选择 Assign Frame From Camera(从摄像机分配帧)。可以通过摄像机实例子项上的脚本进行微调(视野、远近裁剪面)。
2.2.4. roof_group
该预制体在后甲板楼(aftercastle,船只抬高的后部)以及船只设计需要的话前甲板楼之上添加屋顶结构。
- 放置: 将 roof_group 预制体添加到船只根实体的恒等位置(0,0,0)。
- 结构: 该预制体包含 15 种不同的屋顶变体和平台选项。将适合你船只的平台网格作为 MetaMesh 添加到平台子实体,然后定位屋顶变体以适应你的几何形状。
着色与标签:
- 布料元素(帆布屋顶、遮阳篷): 分配 sail_mesh_entity 标签。这会使布料被染成与阵营帆色相匹配的颜色。
- 木质结构元素: 在资源浏览器中为相关木材材质分配 auto_factor_color 标签。这会使木材的颜色与根实体上 ShipColorAssigner 中定义的船体颜色相匹配。
- 其他布料元素: 在资源浏览器中分配 faction_color 标签(应用于所有 LOD)。这会施加一种通用的阵营颜色色调。
2.2.5. figurehead_group
船首像(figurehead)是船首处雕刻的装饰元素。在玩法方面,它还提供属性加成(增加撞击伤害、士气加成等),使其既是装饰品又是升级部件。
- 放置: 将 figurehead_group 预制体添加到船只的恒等坐标处。
- 结构: 该预制体包含 17 种默认船首像变体,以及用于船只默认(未升级)状态的基座(base)和平台(platform)子项。如果你希望在应用任何升级之前就有默认船首像可见,请将适当的网格作为 MetaMesh 分配给基座和平台子项。
- 添加新类型: 新的船首像变体必须作为子项添加到主预制体中,其属性和描述必须在 ship_upgrade_pieces.xml 和 ship_slots.xml 中注册。
- 可见性: 与大多数其他升级部件不同,船首像是通过在游戏世界中探索发现的,而不是在港口购买的。不过,在使用 EditorShipUpgradeViewer 时,它们仍会出现在编辑器的升级预览中。
2.2.6. battlements_holder_aft
安装在后甲板楼上的防御战盾,用于保护船尾部队。通常用于较重型的战舰。
- 设置: 在船只根节点下的恒等位置创建一个名为 battlements_holder_aft 的空实体。
- 添加 battlement_shield_group_aft 嵌套预制体作为子项。
- 配置: 可以添加多个实例。战盾预制体的每个实例都包含针对不同升级等级和损毁状态的不同视觉状态。可以在每个实例中添加额外的子项作为损毁粒子效果,遵循船只主燃烧系统中使用的相同结构。
2.2.7. deck_upgrade_holder
该实体包含 deck_upgrade_assets_nested 预制体,处理在更高升级等级下出现在甲板上的交互式和被动资产。
- 放置: 将 deck_upgrade_assets_nested 预制体添加为该容器下的子项。可以在甲板上的不同位置放置多个实例。
- NavMesh 约束: 由于这些资产具有物理体,其下方不能烘焙 NavMesh。在物理对象下方烘焙 NavMesh 会导致 AI 寻路错误。
组件分解:
- 可交互资产: 名为 deck_ammo_1、deck_ammo_2、deck_ammo_3、deck_javelin_2 和 deck_javelin_3 的子项是可交互对象。玩家和 AI 代理可以与这些对象交互,在战斗期间补充箭矢和投掷武器。
- 被动资产: 该预制体中的所有其他子项纯粹是没有交互功能的视觉升级装饰。
2.2.8. ship_ballista_holder
一个包含完整弩炮升级的嵌套预制体——武器本身、所有弹药类型变体、代理交互点以及它所在的甲板平台。
- 放置: 将此预制体直接添加到根实体下。
- 标签: 为主容器实体分配 upgrade_slot 标签和 fore 标签。upgrade_slot 标签将其注册到升级系统;fore 标签将其标识为前向武器,并使其与 battlements_holder_fore 互斥(一艘船不能同时拥有弩炮和前甲板战盾)。
子项分解:
- ballista_platform: 一个抬高的甲板平台,为弩炮操作者提供更好的射界。该平台仅在装备弩炮升级时才处于激活状态。
- 标签: 为该子项分配 platform 标签。
- NavMesh 约束: 该平台不得高于已烘焙甲板 NavMesh 1.5 米以上。游戏不会为此平台生成单独的抬高 NavMesh,因此代理必须能够从现有甲板 NavMesh 踏上该平台。如果它太高,代理将无法到达弩炮。
- 弹药类型子项: 其余每个子项代表一种不同的弹药类型(标准弩箭、火焰弩箭等)。所有弹药子项必须放置在完全相同的坐标处——游戏通过根据加载的弹药类型切换可见性来在它们之间进行切换。每个子项必须有一个唯一的标签来标识其弹药类型。
2.2.9. battlements_holder_fore
安装在前甲板楼(forecastle,船只抬高的前部)上的防御盾牌。
- 设置: 在恒等位置创建一个名为 battlements_holder_fore 的空实体。
- 添加 battlement_shield_group_fore 嵌套预制体作为子项。
- 互斥性: 该组件与 ship_ballista_holder 互斥。一艘船不能同时拥有前甲板战盾和弩炮。确保此容器上的标签使用 fore 标识,以便升级系统正确强制执行这种互斥性。
2.2.10. ram_group
撞角(ram)是用于撞击敌船、在碰撞时造成船体伤害的加固船首延伸部分。
- 放置: 将 ram_group 嵌套预制体添加到船只的恒等位置。
- 结构: 该预制体包含 8 种预定义的撞角变体和 1 个适配器网格。放置并调整这 8 种撞角变体的朝向以适应你船只的船首形状,然后将适当的甲板延伸或船首平台网格作为 MetaMesh 添加到适配器实体。
- 标签: 升级和伤害系统所需的所有标签都已预定义在撞角预制体的子项上。可以按照现有模式向该预制体添加新的撞角变体,并在相关的 XML 文件中注册。
2.3. 装饰与 VFX 组件
该组包含纯视觉元素。它们的缺失不会破坏船只的功能或玩法,但对于船只在游戏中看起来和感觉正确至关重要。
2.3.1. wetness_decals
这些贴花模拟外部船体上的水花痕迹,显示波浪拍打船侧时留下的湿润痕迹。
- 设置:在船只根节点下创建一个空实体作为直接子项(不要放在 mesh_holder 或 ship_water_effects 内部)。将其命名为 wetness_decals,并为其分配 wetness_decals 标签。
- 在其下添加子实体。每个子项必须拥有一个 Decal(贴花)组件,并分配所需的湿润材质。
- 将每个贴花相对于船体表面进行定位和定向。贴花的局部向上轴被用作其表面法线——确保它指向远离船体表面的方向,否则系统无法正确判断水花粒子是否足够靠近以激活该贴花。
- 行为:当船体同侧附近有活跃的水花粒子时,贴花会淡入显现,然后在大约 6 秒的非活动状态后逐渐淡出。
2.3.2. rudder_objects
当你希望在船上有一个可见的物理舵,它能够响应船只转向而旋转,即使该转向并非由 ShipControlRudder 控制时使用(即该舵仅是视觉效果,不具备交互性)。
- 设置: 将适当的舵网格作为 MetaMesh 添加到该容器的子实体。
- 标签: 为包含该网格的实体分配 rudder_rotation_entity 标签。游戏会读取此标签来查找视觉舵,并将其旋转角度与船只当前的转向输入同步。
2.3.3. ship_water_effects
ShipWaterEffects(ship_water_effects)是一个脚本组件,为船只添加所有与水相关的视觉效果。它纯粹是视觉性的,对物理或玩法逻辑没有影响。
前提条件: 在添加此脚本之前,船只的浮力(浮子体积)必须已完全设置好。ShipWaterEffects 会读取浮子配置,以确定用于粒子放置的水线位置。
该脚本附加在船只根节点的子实体上——而不是根节点本身。创建一个名为 ship_visual_only 的子实体,并将 ship_water_effects 脚本添加到其中。ship_visual_only 标签将此脚本的范围限定在仅视觉实体内,使其与物理和玩法逻辑分离。
[ship_root] └─ [ship_visual_only] ← ShipWaterEffects 脚本位于此处
功能概览:
| 功能 | 描述 |
|---|---|
| 航迹(Wake) | 移动船只身后水面上留下的尾迹。形状和大小根据船体网格自动推导。 |
| 移动粒子(Movement Particles) | 船只航行时沿船体两侧持续产生的水花喷溅。 |
| 水花粒子(Splash Particles) | 在水线处由速度触发的爆发式粒子。阈值:小≥2 m/s,中≥5 m/s,大≥8 m/s。 |
| 船体内部水体模拟(In-Hull Water Simulation) | 在船体内部渲染的模拟水面。会自动对波浪进入事件和降雨做出反应。 |
| 泡沫尾迹贴花(Foam Trail Decals) | 船只移动时在船首生成的泡沫斑块,会随时间漂移和淡出。需要场景中有贴花渲染器。 |
| 湿润贴花(Wetness Decals) | 在活跃水花粒子附近显得明显湿润、并随时间变干的船体贴花。设置方法见 2.3.1 节。 |
| 降雨交互(Rain Interaction) | 船体内部水面会自动对场景降雨密度做出反应。 |
注意: 你不需要手动放置任何粒子实体。所有粒子位置都会在启动时通过对 body_mesh 实体进行射线检测自动计算。确保 body_mesh 存在,并具有带有准确包围盒的有效 MetaMesh。如果船只带有撞角,船首粒子条带会自动延伸以覆盖撞角尖端——不需要额外设置。
可配置参数:
船体内部水体模拟:
- Water Simulation Bounding Box(水体模拟包围盒,默认: 1,1,1)—— 包围体积的 XYZ 范围。使用 Reset Water Simulation Bounding Box(重置水体模拟包围盒) 可根据 render_to_depth 网格自动计算。
- Hull Water Simulation Resolution Scale(船体水体模拟分辨率比例,默认: half)—— 选项: one、half、quarter、one_eight、one_sixteenth。数值越低性能越好。
- Hull Water Splash Water Multiplier(船体水花水量倍增器,默认: 1.75)—— 在水花事件发生时,缩放船体内部的波浪位移强度。
- Ship Hull Height Type(船体高度类型,默认: Small)—— 高舷船只请使用 Large。选项: Small、Medium、Large。
移动粒子:
- Movement Particle Type(移动粒子类型,默认: Small)—— 小型船只使用 Small,较大船只使用 Medium 或 Large。
- Movement Particle Height Offset(移动粒子高度偏移,默认: 0.34)—— 相对于计算出的水线的垂直偏移量(米)。
- Movement Particle Surface Distance Offset(移动粒子表面距离偏移,默认: 0.7)—— 粒子起点距船体表面的距离。
水花粒子:
- Splash Particle Height Offset(水花粒子高度偏移,默认: 0.4)—— 水花粒子放置相对于水线的垂直偏移。
- Splash Particle Surface Distance Offset(水花粒子表面距离偏移,默认: 0.7)—— 水花粒子起点距船体表面的距离。
编辑器调试工具(仅限编辑器,出货构建中无效果):
- Reset Water Simulation Bounding Box(重置水体模拟包围盒) —— 根据 render_to_depth 网格自动计算包围盒。
- Re-render Depth Texture(重新渲染深度纹理) —— 在修改 render_to_depth 网格后强制重新渲染深度纹理。
- Reset In-Hull Water(重置船体内部水体) —— 将船体水体模拟重置为初始状态。
- Show Water Simulation Bounding Box(显示水体模拟包围盒) —— 在视口中绘制包围盒。
- Show Movement Particles / Show Splash Particles(显示移动粒子/显示水花粒子) —— 在每个粒子起点绘制调试标记。
- Show Water Balance Plane(显示水平衡平面) —— 将计算出的水线可视化为一个红色平面。
- Show Wetness Decal Values / Force Wetness Decal To Full(显示湿润贴花数值/强制湿润贴花至最大) —— 用于检查湿润贴花放置和不透明度的工具。
战役地图行为: 在战役地图(Main_map 场景)上,此脚本会自动禁用所有粒子和模拟逻辑。战役地图上不会产生视觉开销——只需要实体结构存在即可。
2.3.4. ship_burning_system
该实体包含与船只燃烧机制相关的所有视觉和音频内容——火焰粒子、光源和声音节点。该系统旨在以受控的顺序逐步在船上蔓延火焰。
a) 粒子放置层级结构:
ship_burning_node 预制体被归类到特定的父实体中,以定义火焰可以出现的位置。这些父节点必须存在于 ship_burning_system 实体内部:
- railing_parent: 沿栏杆放置燃烧节点。
- ship_deck_parent: 在开放甲板上的随机位置放置燃烧节点。
- deck_upgrade_parent: 在甲板升级资产上及其周围放置燃烧节点。
- mast_parent: 在每根桅杆下方的甲板区域放置燃烧节点。
b) BurningNode 配置:
每个 ship_burning_node 预制体都包含 BurningNode 脚本和一个粒子系统子项。
- Node Index(节点索引,关键): BurningNode 脚本中的 Node Index 值控制火焰蔓延的顺序。为沿逻辑蔓延路径相邻的节点分配连续、唯一的整数(0、1、2、3……)——例如,从船尾到船首对栏杆节点进行编号,会使火焰可见地沿栏杆按顺序蔓延。
- 音频限制(重要): 移除燃烧节点内部所使用粒子系统中的所有声音文件路径。燃烧系统通过 sound_parent 拥有自己专门的声音管理。如果在单个粒子上保留声音,会导致多个重叠的音频源和响亮、错误的声景。
c) 灯光与声音:
- light_parent: 包含点光源实体。将这些灯光放置在燃烧节点集群附近,以营造逼真的火光照明效果。灯光会根据 ShipBurningSystem 脚本中的火焰进度值自动淡入淡出。
- sound_parent: 包含 burning_sound_node 预制体。根据船只大小,在船周围放置 2 到 6 个这样的节点。这些节点仅在其附近的火焰粒子处于活跃状态时才会触发燃烧声音。
d) ShipBurningSystem 脚本(根设置):
- Start Fire / Stop Fire(开始燃烧/停止燃烧): 编辑器按钮,用于在不启动游戏的情况下预览完整的燃烧序列。
- Spread Rate(蔓延速率): 控制火焰在船上蔓延的速度。数值越高,燃烧越快、越猛烈。
- All Fire Mode(全部点燃模式): 同时激活所有火焰粒子,便于直观检查节点放置情况。
- Small Hit Debug(小型命中调试): 启用此项后,瞄准船只并按鼠标中键可以模拟一次小型局部火焰命中。
- Min/Max Fire Progress For Light(灯光的最小/最大火焰进度): 控制灯光激活的时间线。
- Min(最小值): 点光源开始淡入时的火焰进度值(0–1)。
- Max(最大值): 灯光达到峰值强度时的火焰进度值。
- Max Light Intensity(最大灯光强度): light_parent 下的灯光在火焰强度达到峰值时所能达到的最大亮度值。
2.3.5. rope_cosmetics_holder
该容器包含在船只各点之间系挂的装饰性绳索——索具线、系泊绳以及其他增添氛围的绳索细节。
- 预制体: 对每根绳索使用 simple_rope_nested。将每根绳索的起点和终点子实体放置在船上所需的锚定点上。
- 配置: 通过起点子实体上的脚本调整以下内容:
- fixed size(固定长度): 绳索是具有固定长度,还是根据端点之间的距离下垂。
- loose amount(松弛量): 绳索在两端点之间下垂的程度(悬链线曲线深度)。
- default length(默认长度): 绳索自然未拉伸时的长度。
- 视觉属性: 绳索粗细、基于长度的纹理平铺以及其他视觉参数,通过绳索实体上材质的自定义网格参数(custom mesh parameters)进行控制。
2.3.6. brazier_holder
火盆(Braziers)提供了燃烧的煤炭盆,弓箭手可以用它点燃火箭。根据船只设计,该组件与某些盾牌升级配置可以互换使用——或互斥使用。
- 放置: 将 brazier_b 或 brazier_d 预制体作为子项放置在此容器下,位于船只边缘或甲板上合适的位置。标签已在预制体上预定义——无需额外的标签设置。
- 可以放置多个火盆,它们的位置应便于站立的代理使用,而无需离开其战斗位置太远。
2.3.7. ship_water_clip(SDF 系统)
SDF(带符号距离场,Signed Distance Field)系统防止海水在视觉上出现在船体内部——如果没有它,海面会穿透船体几何体,看起来会不正确。
- 模型准备: 创建一个自定义 3D 网格,紧密贴合甲板线以下船体的外部形状,并略微延伸至甲板水平线以上,以形成一个密封的体积。此网格定义了”干燥”的内部区域。
- 命名约定: 网格名称必须以前缀 sdf_ 开头(例如 sdf_dromon)。引擎在导入时会自动将带有此前缀的任何网格处理为 SDF 数据。
设置:
- 将 ship_water_clip 预制体添加到船只层级结构中。
- 在此预制体内找到 signed_distance_field 脚本。
- 将你准备好的 SDF 网格资产分配给该脚本。
验证: 在脚本中启用 Visualize SDF(可视化 SDF) 复选框,以在编辑器视口中将场渲染为彩色体积。验证该体积完全包围了甲板以下的船体内部。

2.3.8. deckwater(高度图模拟)
该系统模拟船只甲板上的积水和晃动的水——即波浪冲过船舷时积聚的可见水体。
- 资产: 需要一个简化的”假甲板”网格。该网格用于生成模拟所读取的俯视深度纹理(高度图)。
- 设置:
- 在 mesh_holder 下添加该假甲板网格作为子实体。
- 为该实体分配 render_to_depth 标签。水效果系统会将其(连同所有其他带有 render_to_depth 标签的对象,如 oar_seats 和甲板家具)包含在深度渲染中。
- 设置完成后,导航到 ship_water_effects 子实体,并在 ShipWaterEffects 脚本中点击 Re-render Depth Texture(重新渲染深度纹理) 来烘焙深度纹理。
- 调试: 在场景选项(Scene Options)窗口中增大 Water Strength(水体强度) 值,并在可见性(Visibility)窗口中启用 Enable Physics(启用物理),以便在编辑器中观察甲板积水模拟行为。

2.3.9. torch_holder
该容器包含灯笼和火炬,为船只在夜晚和黑暗场景中提供环境照明。
- 预制体: 为每个光源位置添加 nord_lantern_nested 作为子项。
- 每个灯笼预制体包含:
- collision_sphere: 一个用于碰撞交互的小型物理球体(例如代理擦过灯笼)。
- swinging_object: 灯笼中随船只运动而物理摆动的部分。为该子项分配 swinging_entity 标签。该子项包含光源实体和在视觉上摆动的灯笼网格。
- nord_lantern_part_02: 不摆动的静态安装支架或链条。该部分相对于船只保持固定。
2.3.10. knobs_holder
该容器包含帆上绳索系挂的甲板级锚点。它们是水手用来固定索具绳索的系缆桩、系柱和系索栓架。
- 父标签: 为 knobs_holder 实体本身分配 knob_points_parent 标签。帆系统使用此标签来定位船上所有可用的绳索锚点。
可用预制体:
- bollard_a
- cleat_a
- belaying_pins_a
- belaying_pins_b
- 设置: 每个预制体内部都有作为精确绳索端点锚定的子实体。为这些子实体中的每一个分配 knot_point 标签。你可以根据索具设计的需要复制并放置任意数量的锚点预制体。帆系统会自动使用最近的 knot_point 来从每个帆的控制骨布线绳索视觉效果。
