# 非人类角色(NPC) ## 创建各种类型生物的一般准则 Dagor 引擎支持创建任何骨骼动画对象(角色)。 但是,本指南重点介绍不涉及 IK (反向运动学)、上半身或下半身动画、复杂动画混合或附加动画的简单示例。阅读本指南后,您将能够创建具有任意数量肢体的角色。此外,我们将设置动画状态,以便在角色动画之间实现平滑过渡。 ## 3ds Max 中的示例场景 您可以下载包含已做好导出准备的模型的场景: {download}`3dsMax2024Files.zip `. ## Dagor Engine 中的示例 这些示例旨在用于基于 daNetGame 的项目。这些文件包括即用型游戏资产:一条鱼和一只乌鸦。由于着色器相关问题,尚未测试与 War Thunder 的兼容性。 下载存档: {download}`creatures.zip `. 将文件解压缩到项目的 `dev` 目录(游戏版本中未包含的 testing 目录)中。例如,`//develop/assets/dev/gameRes/`。解压后,路径应如下所示: `//develop/assets/dev/gameRes/creatures`. 如果所有内容都设置正确,则加载 [Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) 并选择乌鸦资产{bdg-dark-line}`1` 将导致无错误加载。 单击{bdg-dark-line}`2` 查看错误日志。突出显示的部分表示加载成功。 ```{note} 场景与 3ds Max 2024 或更高版本兼容。 ``` ## 骨架骨骼结构:功能和场景配置 我们来分析一下乌鸦场景。打开文件 {bdg-dark-line}`0` `crow_detailed_tpose.max`. 确保在文件名中指定它是角色的 T 姿势。模型必须包含根骨骼 {bdg-dark-line}`3`。命名很灵活,但如果您打算使用现有的`.blk`文件作为模板,最好将其命名为`root`。此骨骼用于移动整个场景。此外,必须定义`Body`骨骼 {bdg-dark-line}`4` 。 ```{seealso} 有关更多信息,请参阅 [.blk 文件格式](../../dagor-tools/blk/blk.md). ``` 对于具有单独的上下动画的复杂模型,可能会根据特定事件同时播放不同的动画。在这种情况下,骨骼名称必须清楚地表明它们对程序员的用途。在此示例中,相同的动画始终适用于所有骨骼,因此 '`Body`' 紧跟在 '`root`' 之后。 在定义用于生成动画依赖项的属性时,这将变得至关重要。 ```{note} 对于更复杂的角色,结构可能涉及一些动作,例如在旋转躯干时奔跑和看着摄像机。此类设置需要高级配置,这超出了本指南的范围。在这里,我们专注于一个更简单、更直接的任务。 ``` 3ds Max 场景必须包括以下强制性功能: - **LODs** (细节级别) {bdg-dark-line}`2`的名称必须一致,例如,`LOD00` {bdg-dark-line}`1`。LOD 中名称不一致将导致[Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md)资源加载。虽然 3ds Max 不鼓励对象使用相同的名称,但 Dagor 引擎需要此约定。要区分对象,请将它们放置在根据其 LOD 级别命名的图层中,如上例所示。 - 对于 **Skin 修改器**,请始终禁用 **双四元数** {bdg-dark-line}`6` 并设置每个骨骼 {bdg-dark-line}`5` 的点数以匹配项目的 `application.blk`中指定的配置。有关更多详细信息,请参阅 **Dagor中的皮肤参数** 部分: [使用皮肤修改器](#working-with-the-skin-modifier)。 ```{seealso} 有关更多信息,请参阅 [application.blk](../../assets/all-about-blk/application_blk.md). ``` - 将蒙皮对象存储为 **可编辑网格** {bdg-dark-line}`7` 以确保点权重在导出后准确反映在 Dagor 中。这些步骤有助于在 Dagor 中精确复制蒙皮修改器的行为。 - 使用 **Selection Sets** {bdg-dark-line}`8` 在导出过程中更轻松地选择对象。例如,要导出`LOD00`,请创建一个名为`lod00`的组,其中包含 `LOD00` 图层中的所有场景骨骼和所有对象。 场景中的每个骨骼都必须包含 **自定义属性**,以便 Dagor 将它们识别为骨骼。以下是乌鸦骨架所需的最低配置: ```text animated_node:b=yes // 指定对对象进行动画处理 collidable:b=no // 禁用所有碰撞 massType:t="none" // 没有质量,但对象是物理的 renderable:b=no // 从渲染中排除 cast_shadows:b=no // 从阴影生成中排除 ``` ## 添加基本物理 要在 Dagor 中正确初始化场景,请使用 **自定义属性** {bdg-dark-line}`2` 将物理属性分配给至少一个骨骼。 如果没有物理特性,引擎将无法生成有效的骨架。以下是 '`head`' 骨骼 {bdg-dark-line}`1` 的示例配置: ```text animated_node:b=yes // 指定对对象进行动画处理 collidable:b=no // 启用碰撞处理,但需要进一步设置 massType:t="box" // 指定质量计算类型 collision:t=capsule // 指定碰撞类型;请咨询您的导师以获取替代方案 physObj:b=yes // 启用对象的物理特性 density:r=2000 // 用于质量计算的密度 renderable:b=no // 从渲染中排除 cast_shadows:b=no // 从阴影生成中排除 ``` ```{seealso} 有关更多信息,请参阅 [绑定、蒙皮和导出新角色](../dng-rig-skin-export-new-char.md/dng_rig_skin_export_new_char.md). 下载示例文件以查看骨骼的自定义属性,例如 '`Bip*`'。 这些属性决定了物理骨架的生成方式。 ``` ## 使用 Skin Modifier 使用 **蒙皮 修改器** 最关键的方面是控制每个顶点的骨骼数量。按照惯例,此值设置为每个顶点 4 个骨骼。此参数在项目的通用配置文件 `application.blk`中定义。其他必需的设置已在前面介绍过。 `application.blk`中的示例配置: ```text dynModel{ descListOutPath:t="dynModelDesc" separateModelMatToDescBin:b=yes ignoreMappingInPrepareBillboardMesh:b=yes enableMeshNodeCollapse:b=no maxBonesCount:i=318 // 这是无效的!着色器限制将骨骼计数限制为 200。 // 超过 200 将导致 daBuild 期间出现错误。 setBonePerVertex:i=4 // 每个顶点的骨骼数量 } ``` ## 创建 LOD:动态模型的特殊注意事项 创建 LOD 的主要规则是确保所有 LOD 级别的命名一致。以 crow 为例: 如图所示,LOD 共享相同的基本名称,但放置在单独的图层中。每个 LOD 可以包含多个蒙皮对象。此方法非常有用,尤其是当单个对象的三角形总数超过 65,000 个三角形的限制时。如果您的模型超出此限制,请将其分成多个部分。 对于每个具有 **Skin modifier**(蒙皮)修改器**的模型,必须添加以下 **Custom Properties(自定义属性)**: ```text animated_node:b=yes // 指定对对象进行动画处理 collidable:b=no // 禁用所有碰撞 massType:t="none" // 表示此对象没有物理质量 ``` 确保所有蒙皮对象 {bdg-dark-line}`1` 都具有指定的属性 {bdg-dark-line}`2`: 要有效管理 **自定义属性**,请使用编辑器或查看器工具。 ```{seealso} 有关更多信息,请参阅 [*Dagor 2 Fast Editor 用户属性*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/fast_editor_user_properties.md). ``` ## 动态模型的材质 让我们检查一下分配给场景中的蒙皮模型的材质。在这种情况下,使用的材质是`crow_base`和 `Dagor Dagorrat Material 2` {bdg-dark-line}`0`。要查看所有可用的 **动态材质**,请打开下拉菜单并导航到相关部分{bdg-dark-line}`1`。 虽然每种材质类型都需要专门的文档,但我们将重点介绍 [PBR](https://en.wikipedia.org/wiki/Physically_based_rendering) 光照的最简单、最通用的选项:**dynamic_simple** {bdg-dark-line}`2`。此材质支持标准纹理,如 **albedo**(具有可选的透明度)、**normal**、**smoothness**和 **metalness** 贴图。在本例中,纹理为: - `crow_body_a_tex_d.tif` (albedo) - `crow_body_a_tex_n.tif` (normal map) 如果存档已正确解压缩,则可以在以下路径中找到这些纹理: `//enlisted/develop/assets/dev/gameRes/creatures/characters/crow`. 将纹理分配给适当的插槽 {bdg-dark-line}`3`。要启用透明度,请添加 **atest** 属性 {bdg-dark-line}`4`并将其值 {bdg-dark-line}`5` 设置为 `127`。这将控制 Alpha 测试阈值,其中中间亮度决定透明度。此外,启用双面渲染 {bdg-dark-line}`6`,因为乌鸦羽毛必须在两侧渲染。 :::{grid} 2 ::: 在继续导出之前,请确认此材质已应用于所有蒙皮对象。 ## 导出动态模型 如果之前正确准备了 **选择集** {bdg-dark-line}`1`,则导出非常简单。在 crow 场景中,选择名为 `lod00` {bdg-dark-line}`2` 的集。此作将高亮显示 `LOD00`图层和所有关联的骨骼。 接下来,导航到 **Utilities**,然后选择 **Dagor Scene Export**。如果此选项不可用,请使用 **Sets** 按钮添加它。在 **Dagor Export** 设置中,确保启用以下选项: - **Export hidden objects** - **Export selected objects only** 这些选项对于每次导出都是必不可少的。最后,单击 **Export DAG**。 ### 重要的命名约定 Dagor legacy 约束需要特定的命名约定。从 '`creatures.zip`' 档案中提取的文件必须遵循此格式,以保持与 '`.blk`' 脚本和项目构建管道的兼容性。 对于动态模型: - 附加后缀`_dynmodel`。 - 使用`.lodXX`后缀指定 LOD,其中`XX`是 LOD 级别。 例如,crow 模型最详细的 LOD(00) 应命名为crow_detailed_a_dynmodel.lod00.dag. - **绿色文本**:可根据您的命名需求进行定制。 - **红色文本**:已修复且必须,以确保在构建过程中正确处理并定义 LOD 编号。 ```{note} 导出后,您可能会遇到如下错误: 出现这些错误是因为骨骼缺少指定的 **Dagor** 材料。指定材质无法解决此问题;可以放心地忽略它。 ``` 对其他两个 LOD 重复导出过程,并将它们命名为: - `crow_detailed_a_dynmodel.lod01.dag` - `crow_detailed_a_dynmodel.lod02.dag` 导出完成后,在 [Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) 通过选择 `crow_lo_a_dynmodel` {bdg-dark-line}`1`: 如果一切都正确完成,模型应该可以正确加载。 ## 导出动画 从本质上讲,动画只是与模型关联的骨骼运动的记录。 ```{important} - 骨骼数量、命名和层次:这些必须在动态模型和动画文件之间完全匹配。 - 任何不匹配都可能导致奇怪的动画层次结构或无法完全显示动画。 ``` 打开文件`crow_detailed_idle_b.max`,其中包含空闲移动的动画。选择场景中的所有骨骼;应该有 **195 个选定的对象**,包括所有辅助对象。 在 **Dagor Export** 面板中,确保以下内容: 1. 启用 **Export selected objects only** 按钮 {bdg-dark-line}`1`。 2. 显式设置导出v的动画键范围,从 0 帧到 150 帧。 ```{note} 时间轴上显示的动画范围与导出无关。您必须在导出设置中手动指定密钥范围。 ``` 启用复选框 {bdg-dark-line}`4`可显著提高动画精度,在这种情况下,这对于防止诸如“滑动”脚等视觉错误至关重要。 ```{note} 以高精度导出动画会使文件大小增加数百倍。仅在确实需要时才使用此选项。 ``` 如果没有这些复选框,动画将按层次结构压缩,随着时间的推移会累积小错误。这可能会导致明显的视觉差异。启用高精度可最大程度地减少这些错误,从而确保更流畅的播放。 如果场景中没有缩放动画,请取消选中 **scaling checkbox** (如本乌鸦示例)。 点击 **Export Animation** 按钮 {bdg-dark-line}`3`。 动画文件的命名和位置约定与动态模型的命名和位置约定类似: - 将动画存储在: `//develop/assets/dev/gameRes/creatures/animation/crow` - 使用 `.a2d` 扩展名。 - 命名准则: - 使用与动态模型相同的基本名称,但省略与 LOD 相关或特定于动态模型的后缀。 - 避免在文件名中使用关键的脚本处理器关键字(例如,与动态相关的术语)。 在此示例中,将动画另存为: `crow_detailed_idle_b.a2d`. 在此文件旁边,还应有一个名为 `crow_detailed_idle_b.a2d.blk`. 此文件包含动画的各个属性和设置。 **示例:** ```text name:t="crow_detailed_idle_b.a2d" // 链接到此脚本的动画的名称 opt:b=no // 已禁用保守优化。 posEps:r=0.001 // 项目构建期间的位置压缩精度。 // 较高的值(例如,0.1 > 0.01)会减小文件大小,但会降低准确性。 rotEps:r=0.001 // 旋转压缩精度。值越高,精度越高。 sclEps:r=0.1 // 缩放压缩精度(如果适用)。 ``` 这是用于导出后处理的`.blk`脚本的示例。仔细调整压缩值以平衡文件大小和动画精度。 导出后,在 [Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) 中打开动画。如果选择导出的动画 (`crow_detailed_idle_b`),最初可能什么也看不到: **显示动画的步骤:** 1. 分配与动画关联的动态模型 {bdg-dark-line}`1`。 2. 重新选择动画 {bdg-dark-line}`2`。 此时,乌鸦 {bdg-dark-line}`3` 应该出现在动画的第一帧中,而不是默认的 T 姿势。 **播放动画:** - 要播放动画,请单击播放按钮 {bdg-dark-line}`4`。 - 默认情况下,动画播放速度非常快。使用速度滑块{bdg-dark-line}`5`降低播放速度(例如,将其设置为`0.5x`以获得更流畅的观察)。 在此阶段,所有必要的数据都已从 3ds Max 导出: - 动画 - 骨骼结构 - 等级制度 - 模型及其 LOD 最后一步是更新`.blk`脚本以定义每个组件(例如骨骼、动画、模型)的角色,以便集成到 Dagor Engine 中。 ## 在 Dagor 和 Resource Integration 中使用动态模型的原则 在 `creatures.zip`中,与模型一起找到的`.blk`文件是自动为游戏准备、转换和生成资源的脚本。 这些脚本是用 Dagor 的内部语言编写的,定义了管理游戏实体和对象的特定流程。 ```{note} **更改后重新加载:** - 某些`.blk`文件(例如,`.folder.blk`)仅在重新加载[Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md)或 [daEditor](../../dagor-tools/daeditor/daeditor/daeditor.md)的 daeditor.md 中)。 - 相反,与动画相关的文件可以动态编辑,并且更改会立即生效。 ``` `.folder.blk` 文件处理它所在目录的所有内容及其子目录。这在处理大量资源时特别有用。 **示例:处理动画** `//develop/assets/dev/gameRes/creatures/animation/.folder.blk` ```text export{ gameResPack:t="anims.grp" // 将处理后的动画资源导出到指定的游戏资源包 exported:b=yes // 执行导出 } virtual_res_blk{ // 创建虚拟资源 find:t="^(.*)\.a2d$" // 在目录树中找到所有 *.a2d 文件 className:t="a2d" // 分配 “a2d” 类,将它们标记为动画对象 contents{ opt:b=yes // 启用保守优化 posEps:r=0.01 // 位置的压缩精度 rotEps:r=0.2 // 旋转的压缩精度 sclEps:r=0.1 // 缩放的压缩精度 } } ``` 此脚本: 1. 将动画导出到`anims.grp`游戏资源包中。 2. 查找所有`.a2d`文件,为它们分配 “a2d” 类,并将它们作为动画处理。 3. 应用默认阈值的压缩,以平衡文件大小和动画质量。 **示例:处理动态模型** `//develop/assets/dev/gameRes/creatures/.folder.blk` 此脚本稍微复杂一些,但遵循相同的结构。 ```text scan_assets:b=yes // 搜索对象 scan_folders:b=yes // 搜索目录 export{ ddsxTexPack:t="creatures.dxp.bin" // 处理纹理并将其存储在此游戏资源中 gameResPack:t="creatures.grp" // 在此处存储已处理的模型和虚拟对象 } virtual_res_blk{ // 创建虚拟资源 find:t="^((.*)_dynmodel)\.lod00\.dag$" // 查找动态模型文件 stopProcessing:b=false // 继续在其他块中处理此对象 className:t="skeleton" // 从动态模型生成骨架 name:t="$2_skeleton" // 指定骨架名称 contents{ addSkinNodes:b=yes // 将蒙皮节点附加到骨架 reduceNodes:b=yes // 删除没有蒙皮顶点的骨骼 } } virtual_res_blk{ // 创建虚拟资源 find:t="^((.*)_dynmodel)\.lod00\.dag$" // 再次扫描动态模型 stopProcessing:b=false className:t="DynModel" // 将 “DynModel” 类分配给动态模型 name:t="$2_dynmodel" // 为动态模型对象分配名称 contents{ lod{ range:r=3000; fname:t="$1.lod00.dag"; // 将 LOD00 渲染距离设置为 3000 米 } ref_skeleton:t="$2_skeleton" // 指定相应的骨架 } } ``` **关键步骤:** 1. **搜索目录:** - 使用 `scan_assets:b=yes` 和 `scan_folders:b=yes` 以查找对象和目录。 2. **导出纹理和模型:** - 纹理保存在 `creatures.dxp.bin` 中。 - 模型和虚拟对象保存在 `creatures.grp` 中。 3. **生成骨架:** - 查找名为`*_dynmodel.lod00.dag`.的模型。 - 为这些模型创建骨架,删除未使用的骨骼并链接皮肤。 4. **为模型分配属性:** - 为 LOD00 分配`3000`米的渲染距离。 - 将动态模型链接到生成的骨架。 运行脚本后,生成的文件(`creatures.grp` 和 `creatures.dxp.bin`)就可以集成到游戏中了。这些资源: - 包含正确配置的骨架、骨骼和皮肤对象。 - 针对游戏性进行了优化,具有渲染距离和压缩设置等属性。 这些配置可确保所有对象都作为具有特定类和属性的游戏实体进行处理。 ## Dagor 中的真实资源与虚拟资源和对象 **关键概念:** 在使用 Dagor 时,了解 **真实资源**(磁盘上的文件)、**虚拟资源**(引擎创建的实体)和 **转换为游戏实体的虚拟资源** 之间的区别至关重要。 Dagor 引擎将导出的文件(例如,`.a2d`, `.dag`)处理成优化的格式(`.dxp.bin`, `.grp`),以供游戏使用。磁盘上的物理文件表示原始数据,而引擎中的虚拟对象是分配了游戏属性的实体。这些虚拟对象随后被写入二进制游戏资源。 **真实资源与虚拟资源:** 1. **导出的文件:** 来自 3ds Max 等工具的文件包括动画(`.a2d`) 和动态模型(具有 LOD 级别的`.dag`)。这些原始文件是中间资源。 2. **引擎优化:** Dagor 引擎转换导出的数据,应用压缩和处理以满足游戏引擎的要求(例如,减小文件大小、优化性能)。 3. **游戏资源文件:** 最终输出(如 `.dxp.bin` 和`.grp` )是游戏可执行文件唯一识别的格式。脚本 (`.blk`) 将导出的数据处理到游戏实体中。 **示例:Crow 动态模型分解** 从单个动态模型文件中,可以使用`.blk` 脚本生成以下游戏实体: - 骨架 (`crow_skeleton`) - 模型 Shell - 物理模型 - 碰撞数据 值得注意的是,如果对象不需要,物理 {bdg-dark-line}`1` 和碰撞 {bdg-dark-line}`2` 数据可能保持为空,就像乌鸦模型一样。 例如: - **骨架:** 可见,因为它已在脚本中显式处理。 - **物理和碰撞:** 为空,因为脚本没有定义这些组件。 ## 配置 `*_char.animchar.blk` 此脚本将虚拟资源(例如,骨架、模型、物理)组装成具有复杂结构的角色,游戏代码可以有效地管理这些角色。 **示例:** `//develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_char.animchar.blk` ```text //no_anim_dist:r=100 // 超过此距离后,动画将停止(已注释掉) //no_render_dist:r=200 // 超过此距离,模型将停止渲染(已注释掉) //useCharDep:b=no // 此处未使用;如果需要,请查阅特定文档 rootNode:t="root" // 骨架的起始骨骼 dynModel:t="crow_detailed_a_dynmodel" // 角色的动态模型名称 skeleton:t="crow_detailed_a_skeleton" // 角色的骨架名称 animTree:t="crow_detailed_a_animbnl" // 用于混合和规则的动画描述树 physObj:t="crow_detailed_a_phobj" // 角色的物理模型 //ref_states{ // 可选引用状态(已注释掉) // state:t="stand_ground" //} ``` **要点:** 1. 仅对 **虚拟对象** (例如,骨架、模型) 进行作。 2. 不搜索或排序物理文件;所有对象都必须已作为虚拟实体存在。 3. 通过链接组件 (动态模型、骨骼、物理) 来组装更高级别的角色结构。 ## 配置 `*_dynmodel.dynmodel.blk` 此脚本将特定属性应用于单个模型。与处理文件组的`.folder.blk`不同,`*_dynmodel.dynmodel.blk`以单个资源为目标。 **示例:** `//develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_dynmodel.dynmodel.blk` ```text ref_skeleton:t="crow_detailed_a_skeleton" // 指定相应的骨架 lod{range:r=2;} // LOD00 在 2 米处切换到 LOD01 lod{range:r=7;} // LOD01 在 7 米处切换到 LOD02 lod{range:r=15;} // LOD02 在 15 米处关闭渲染 ``` **要点:** 1. **命名约定** 确保精确定位特定动态模型 (`crow_detailed_a_dynmodel`)。 2. **LOD 配置:** - `range:r=2`: 从最高细节 (LOD00) 过渡到较低细节 (LOD01)。 - `range:r=15`: 完全停止渲染超过此距离。 3. 将骨架链接到动态模型 (`ref_skeleton`),确保它使用正确的层次结构。 ```{important} **真实与虚拟:** - 实际资源是原始文件(例如,`.a2d`, `.dag`),而虚拟资源是由引擎创建和优化的实体。 - 游戏资源文件(`.dxp.bin`, `.grp`)是最终的优化输出。 **脚本层:** - `.folder.blk`: 处理资源组。 - `*_char.animchar.blk`: 从骨架、模型和物理等组件组装角色。 - `*_dynmodel.dynmodel.blk`: 使用 LOD 范围等属性配置单个模型。 ``` ## 配置 `*_animbnl.animtree.blk` `*_animbnl.animtree.blk`文件定义动画状态、混合和其他相关配置的规则,例如角色的附加动画。此脚本是最复杂的脚本之一,因为它对动画混合和状态转换进行了详细控制。 ```{seealso} 有关更多信息,请参阅 [daAnimations](../../assets/animation/daanimations.md). ``` **要点:** 1. **顺序执行很重要:** 块和命令必须按照它们定义的顺序执行。例如,必须在使用混合控制器之前声明它。 2. **节点作为单位:**节点** 可以表示对象、模型或骨骼。节点由名称标识,用于配置。 3. **关键文档:** 强烈建议仔细阅读相关文档,以了解控制器、状态和混合技术。 **示例:** `//develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_animbnl.animtree.blk` **脚本分解:** ```text export:b=yes // 处理脚本 root:t="fifo3" // 用于动画混合的根节点 defaultForeignAnim:b=yes // 启用混合外部动画 ``` ```text nodeMask{ // 定义特定节点(在本例中为骨骼)的蒙版。 name:t="body" // 来自 3ds Max 的骨骼名称 node:t="Bip01" // Dagor 识别的根骨骼名称 } ``` - **目的:** 对齐 3ds Max 和 *Dagor* 之间的骨骼命名约定以确保兼容性。例如,`Bip01` 过去用于 3ds Max 中的根骨骼。 ```text stateDesc{ // 指定角色的所有可能的动画状态。 // 在此示例中,状态表示 “flying” 和 “turn right turn while flying” 等条件。 defMorphTime:r=0.15 // 状态之间的过渡时间(变形) defNodeName:t="*" // 应用于所有骨骼(节点) chan{ // “body” 和节点的混合通道 name:t="body" fifo3:t="fifo3" // 控制器类型 nodeMask:t="" // 适用于所有节点 cond_target:i=1 } chan{ // “根”和节点的混合通道 name:t="root" fifo3:t="fifo3_root" nodeMask:t="" cond_target:i=0 } state{ // 示例动画状态 name:t="crow_a_fly_turn_right" // 状态名称 body{ name:t="crow_a_fly_turn_right"; } // 将状态链接到 “body” 的动画 } } ``` - 状态:表示可以混合多个动画或过渡的高级条件。 - 通道:控制特定节点或骨骼组在动画中的混合方式。 每个动画状态都链接到一个`AnimBlendNodeLeaf{}`块,该块指定实际的动画文件 (`*.a2d`) 及其属性。 ```text AnimBlendNodeLeaf{ a2d:t="crow_detailed_fly_turn_right" // 动画文件 continuous{ name:t="crow_a_fly_turn_right" // 链接到状态的内部名称 key_start:t="fly_turn_right_start" // 从 3ds Max 开始关键帧 key_end:t="fly_turn_right_end" // 从 3ds Max 结束关键帧 time:r=2.0 // 播放时长 own_timer:b=yes // 此动画的独特计时器 eoa_irq:b=yes // 动画结束中断标记 } } ``` - 目的:准备原始动画文件以在定义的状态下使用。 - 键:定义从 3ds Max 导出的特定动画片段。 Blend 控制器管理不同动画状态的混合。 ```text AnimBlendCtrl{ fifo3{ name:t="fifo3" // 控制器的名称 varname:t="fifo3_var" // 供内部使用的变量名称 } fifo3{ name:t="fifo3_root" varname:t="root_ctrl" } } ``` 关键执行步骤:** 1. 定义控制器:首先声明像 `fifo3` 和 `fifo3_root` 这样的控制器。 2. 指定状态:状态(如 `crow_a_fly_turn_right` )将动画链接到逻辑条件。 3. **创建动画节点:** 对于每个状态,都会创建一个`AnimBlendNodeLeaf{}`来准备相应的动画文件。 4. **测试配置:** 使用 Dagor Engine 可视化工具(例如,[Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md)) 来验证设置。 ```{important} - **目的:** `*_animbnl.animtree.blk` 文件建立了一个用于管理动画状态和混合的框架。 - **组件:** 1. **Node Masks:** 定义骨架关系。 2. **State Descriptions:** 将逻辑状态链接到动画。 3. **Animation Nodes:** 准备用于状态转换的动画。 4. **Controllers:** 管理混合逻辑。 ``` 在 [Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) 中查看 {bdg-dark-line}`1` 时,根据此配置应显示以下元素: 1. **骨架节点:** 根节点(`Bip01`)和相关层次结构 {bdg-dark-line}`2`。 2. **混合节点:** 所有已定义的 `AnimBlendNodeLeaf` 元素 {bdg-dark-line}`3`,与动画状态相对应。 3. **控制器:** 所有指定的控制器(`fifo3`、`fifo3_root`)。 4. **状态:** 所有已定义动画状态的列表,如 `crow_a_fly_turn_right`。 ## 在 Asset Viewer 中测试角色 **第 1 步:在 Asset Viewer 中检查文件** 1. 打开 [Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) 并加载与角色 {bdg-dark-line}`1` 相关的所有文件。 **目标:** 确保控制台 {bdg-dark-line}`2' 中不显示任何错误。成功的结果如下所示: 2. **常见检查点:** - 检查链接到角色的每个文件(例如,动画、混合控制器、状态描述)。 - 控制台错误表示一个或多个配置存在问题。 **第 2 步:本地资源建设** 1. ** 启动 `daBuild`:** 将创建的字符包含在 `.grp` 和 `.dxp.bin` 文件中: - 导航至包含角色资源(如`crow`)的文件夹 {bdg-dark-line}`1`。 - 右键单击文件夹并选择 **Export All (PC)** 选项 {bdg-dark-line}`2`。 2. **监控构建进度:*** - 构建过程开始后,可能会花费大量时间,这取决于计算机的性能。 - 构建进度会显示在控制台中。一次成功的构建会以类似 {bdg-dark-line}`1` 的输出结束: 3. ** 整合:** 一旦创建完成,角色就可以加入游戏了。 ### 常见错误 ### 错误: 括号不匹配 缺少或多余的括号会在脚本解析过程中导致严重错误。 **示例:** ```text BLK error 'D:/dagor2/enlisted/develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_animbnl.animtree.blk',228: unexpected EOF: ``` - **原因:** 不匹配的括号会导致 “文件意外结束”(EOF)错误。 - **解决方法:** 仔细检查脚本中的括号对,尤其是深度嵌套块中的括号对。 #### 错误: 数据类型不正确 **示例:** ```text BLK invalid time (type real) value in line 209 of 'D:/dagor2/enlisted/develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_animbnl.animtree.blk': 'sdfsd' DataBlockParser: invalid value 'sdfsd' at line 209 of file '.../crow_detailed_a_animbnl.animtree.blk' ``` - **原因:** 非数字值(如字符串)被分配给数字属性,如 `time`。 - **解决方法:** 检查并更正数值。确保所有数值参数都定义为有效数字(例如,`time:r=2.0`)。 ### 调试技巧 1. **错误行号:** 虽然错误信息会显示行号,但并不总是准确的。错误往往发生在脚本的前面,但只在后面显示。 2. 手动验证:** ** - 验证关键属性(如 `state`、`chan` 和 `AnimBlendNodeLeaf`)的语法。 - 与示例或模板交叉检查以确保一致性。 3. **逐步测试:** - 通过小块添加元素来逐步测试脚本。 - 这种方法能更有效地隔离错误。 ### 小结 测试的**关键步骤:** 1. 验证 [Asset Viewer](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) 中的所有字符文件。 2. 使用 daBuild 执行本地构建,并监控 的成功输出。 3. 处理过程中检测到的任何错误。 **常见陷阱:** - 缺少或多出括号(`{`, `}`)。 - 值类型不正确(如字符串而非数字)。 - 由于延迟检测导致错误发生在不正确的行号上。 通过遵循这些步骤和调试技巧,您可以确保您的角色 功能齐全,并为游戏集成做好准备。 ```{tip} 如果您遇到任何错误或对本文档有任何疑问,请通过 {octicon}`mail;1.4em;sd-text-info` 直接联系作者。 ```