基础格式与文件结构
1. 概述
本游戏采用 XML 文件作为数据定义的主要形式,允许开发者和模组作者通过结构化的文本文件创建、修改和扩展游戏内容。游戏启动时将扫描特定目录下的 XML 文件,并根据其类型和内容载入游戏。
2. 文件系统结构
游戏会从两个主要目录读取数据:Data/ 和 Mods/。这两个目录下包含一系列“包”(Packages),每个包代表一个独立的数据集合,可以是一个核心游戏模块,也可以是一个用户创建的模组。
文件目录结构示例:
├── Data/
│ ├── Pack1/ # 数据包示例 1
│ │ ├── About/ # 包信息目录
│ │ ├── Define/ # 数据定义目录
│ │ └── Translation/ # 翻译文件目录 (当前版本未实装)
│ └── Pack2/ # 数据包示例 2
│ ├── About/
│ ├── Define/
│ └── Translation/
└── Mods/
├── Mod1/ # 模组包示例 1
│ ├── About/
│ ├── Define/
│ └── Translation/
└── Mod2/ # 模组包示例 2
├── About/
├── Define/
└── Translation/
目录说明:
Data/: 包含游戏的核心内容和官方扩展数据包。Mods/: 包含用户自定义的模组数据包。PackN/,ModN/: 每个子文件夹被视为一个独立的“包”。包名应当具有唯一性。About/: 存放包的元数据(Metaproperties)。Define/: 存放各种游戏对象的具体定义。Translation/: 存放多语言翻译数据(当前版本未实装)。
3. XML 文件类型
当前游戏版本主要识别并处理以下三种类型的 XML 文件:
- About 文件: 包含包的基本信息和加载依赖关系。
- Define 文件: 包含游戏内的各种数据定义,如物品、角色、属性等。
- Translation 文件: 用于多语言本地化(当前版本未实装)。
4. About XML 文件
About 文件是每个包的门户,它提供了包的基本信息以及游戏加载时所需的依赖和排序数据。
- 文件位置: 每个包的
About/文件夹下。 - 文件命名: 建议命名为
About.xml。 - 根元素: 必须以
<About>为根。 - 数量限制: 一个包中只能包含一个 About XML 文件。
典型 About 文件示例:
<?xml version="1.0" encoding="utf-8"?>
<About>
<!-- 包的显示名称,用于用户界面 -->
<name>核心</name>
<!-- 包的详细描述,解释其功能或内容 -->
<description>这是一个基础核心模块,除非有完整的代替,否则应该永远作为启动项</description>
<!-- 包的版本号 -->
<version>0.1</version>
<!-- 包的唯一标识符,必须在所有包中全局唯一 -->
<packID>core</packID>
<!-- 加载排序和依赖关系定义 -->
<sort>
<!-- 定义本包加载前必须加载的包的packID列表 -->
<necessary></necessary>
<!-- 定义本包应该优先于哪些包加载,填写那些包的packID列表 -->
<before></before>
<!-- 定义本包应该在哪些包之后加载,填写那些包的packID列表 -->
<after></after>
</sort>
</About>
元素说明:
<name>: (String) 包的显示名称,会显示在游戏的用户界面中。<description>: (String) 包的详细描述,用以解释其功能或内容。<version>: (String) 包的版本号,遵循语义化版本控制(如1.0.0)或简单版本号(如0.1)。<packID>: (String, 必填) 包的唯一标识符。这个 ID 在整个游戏的数据包和模组中必须是全局唯一的,用于识别包及其依赖关系。<sort>: (Object) 包含加载排序和依赖关系的定义。<necessary>: (Array of String) 定义了本包加载前必须加载的包的packID列表。如果这些包未能加载,本包将无法加载。<before>: (Array of String) 定义了本包应该优先于哪些包加载。列表中填写其他包的packID。<after>: (Array of String) 定义了本包应该在哪些包之后加载。列表中填写其他包的packID。
加载机制:
游戏启动时,会首先读取所有 About.xml 文件,构建一个包的依赖图。然后根据 necessary, before, after 标签中定义的规则,确定包的加载顺序。
- 如果多个包定义了相同的
packID,游戏启动时会报错或仅加载其中一个。 - 如果
necessary的包缺失,则当前包无法加载。 before和after标签用于调整加载顺序,以解决同名 Define 数据覆盖问题或确保特定功能的前提条件。
5. Define XML 文件
Define 文件是游戏内容的核心,用于定义游戏中的各种对象、属性和规则。
- 文件位置: 每个包的
Define/文件夹下。 - 文件命名: 可以根据内容自由命名,例如
Items.xml,Characters.xml等。 - 根元素: 其中的每个 XML 文件必须以
<Define>为根。 - 内容: 可以包含任意数量和类别的各种数据定义。
核心约定:
- 基本属性: 所有的顶级定义都必须包含以下三个属性:
defName: (String, 必填) 定义的唯一名称。这个名称在 该类型的数据定义中 必须是全局唯一的。例如,所有ImageDef都有唯一的defName,所有WeaponDef也有唯一的defName,但ImageDef和WeaponDef可以有相同的defName(如TestGunItem和TestGun)。label: (String) 定义的显示名称,用于游戏用户界面。description: (String) 定义的详细描述,用于游戏用户界面或工具提示。
- 覆盖机制: 如果不同包(或同一包内不同文件)中同一类型的数据定义了相同的
defName,则后加载的定义会覆盖先加载的定义。这允许模组轻松地修改或替换原版游戏内容。 - 引用机制: 当一个定义的数据字段需要引用其他数据定义时,可以通过以下两种方式:
- 引用
defName: 直接填写被引用定义的defName。游戏会在加载时解析这些引用。 - 嵌套定义(匿名定义): 直接在引用位置定义一个新的对象,该对象通常没有
defName,是当前定义的私有或匿名部分。
- 引用
典型 Define 文件示例:
<?xml version="1.0" encoding="utf-8"?>
<Define>
<!-- 图片定义 -->
<ImageDef>
<defName>TestGunItem</defName> <!-- 唯一标识符 -->
<path>Resources\Item\TestGun.png</path> <!-- 图片路径 -->
</ImageDef>
<!-- 属性定义 -->
<AttributesDef>
<defName>TestGun</defName> <!-- 唯一标识符 -->
<attack>10</attack>
<defense>3</defense>
<attackSpeed>3</attackSpeed>
<attackRange>10</attackRange>
<attackTargetCount>1</attackTargetCount>
</AttributesDef>
<!-- 武器定义 -->
<WeaponDef>
<defName>TestGun</defName> <!-- 全局唯一标识符 -->
<label>测试枪</label> <!-- 显示名称 -->
<description>一把测试用的枪</description> <!-- 详细描述 -->
<!-- 引用属性定义,通过defName="TestGun"引用AttributesDef中定义的属性 -->
<attributes>TestGun</attributes>
<type>Ranged</type>
<textures>
<!-- 引用ImageDef中的图片定义 -->
<li>TestGunItem</li>
</textures>
<!-- 引用子弹定义,通过defName="yellowBullet"引用BulletDef -->
<bullet>yellowBullet</bullet>
</WeaponDef>
<!-- 子弹定义 -->
<BulletDef>
<defName>yellowBullet</defName>
<label>黄色子弹</label>
<description>一颗黄色的子弹</description>
<!-- 嵌套定义属性,此处的属性是当前子弹特有的匿名属性,没有defName -->
<attributes>
<health>1</health>
<moveSpeed>20</moveSpeed>
</attributes>
<!-- 嵌套定义纹理绘制顺序,包含多个匿名绘制状态定义 -->
<drawingOrder>
<idle_down>
<textures>
<li>yellowBullet</li>
</textures>
</idle_down>
<walk_down>
<textures>
<li>yellowBullet</li>
</textures>
</walk_down>
</drawingOrder>
</BulletDef>
</Define>
示例解析:
ImageDef: 定义了一个图像资源。defName为TestGunItem,表示这是图像定义的唯一标识。path指定了图像文件在文件系统中的相对路径。
AttributesDef: 定义了一组属性集。defName为TestGun。- 包含了攻击、防御等具体数值。
WeaponDef: 定义了一个武器对象。defName为TestGun。label和description提供显示文本。<attributes>TestGun</attributes>: 这里通过defName引用了AttributesDef中名为TestGun的属性集。<textures><li>TestGunItem</li></textures>: 引用了ImageDef中名为TestGunItem的图像定义。<textures>标签下的<li>元素表示一个列表项。<bullet>yellowBullet</bullet>: 引用了BulletDef中名为yellowBullet的子弹定义。
BulletDef: 定义了一个子弹对象。defName为yellowBullet。<attributes>: 这里没有引用已有的AttributesDef,而是直接在此嵌套定义了一组属性。这些属性是yellowBullet特有的,不与其他定义共享defName。<drawingOrder>: 同样采用嵌套定义的方式,为不同的动画状态(如idle_down,walk_down)定义了各自的纹理列表。
6. Translation XML 文件 (当前版本未实装)
此类型文件未来将用于实现游戏的多语言本地化。
- 文件位置: 每个包的
Translation/文件夹下。 - 根元素: 预期的根元素将是
<Translation>或类似的元素。 - 内容: 届时将包含键值对形式的翻译文本,用于替换游戏中硬编码的字符串或 Define 文件中的
label和description。
在此章节中将会介绍各种定义类型及其使用方法
- 图片定义
- 音频定义
- 属性定义
- 行为树定义
- 绘制节点定义
- 绘制顺序集定义
- 派系定义
- 子弹定义
- 物品定义
- 武器定义
- 消息定义
- 事件定义
- 故事定义
- 实体事件处理定义
- 角色定义
- 怪物定义
- 建筑定义
- 瓦片定义
- 地图生成器定义
- 维度定义
- 技能树定义
- 健康定义
定义图片资源
在游戏配置文件中,您可以使用 <ImageDef> 元素来定义图片资源。每个 <ImageDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<ImageDef> 用于加载和配置游戏所需的各种图片资源,包括单张图片、切分后的子图以及调整图片加载时的各项参数。您可以通过它指定图片路径、切分方式、像素密度以及加载时的翻转行为。
参数说明
所有的参数都必须通过嵌套元素的方式进行赋值。
-
<defName>(必需,字符串)- 该图片定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该图片定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该图片定义的具体内容或特殊用途。
-
<path>(必需,字符串)- 指定图片资源的实际存储路径。
- 路径前缀约定:
otherPackID:相对地址: 表示加载otherPackID包下的相对路径图片资源。- 空前缀: 表示加载当前定义所在包的相对路径图片资源。
res:相对地址: 表示加载游戏编译过程中,项目Resources文件夹下的图片资源。res:前缀的优先级高于包 ID 前缀。
-
<wCount>(必需,整数)- 指定将图片在水平方向上切分为多少个子图。要求图片的宽度可以被
wCount整除。
- 指定将图片在水平方向上切分为多少个子图。要求图片的宽度可以被
-
<hCount>(必需,整数)- 指定将图片在垂直方向上切分为多少个子图。要求图片的高度可以被
hCount整除。 - 当
wCount或hCount大于 1 时,图片将被切分为多个子图。子图按照从上到下,从左到右,从 0 开始的顺序进行编号。
- 指定将图片在垂直方向上切分为多少个子图。要求图片的高度可以被
-
<pixelsPerUnit>(可选,整数,默认为16)- 定义图片在游戏世界中绘制时的像素密度。例如,如果设置为 16,则 16 像素宽的图片在绘制时将占据 1 个单位的宽度。
-
<flipX>(可选,布尔值,默认为false)- 如果设置为
true,则在加载时沿 X 轴翻转图片。 - 重要提示: 对于多子图图片,翻转操作是在图片被切分之后进行的。
defName_0始终代表翻转前的图片左上角子图。这意味着先进行裁剪,再对每个子图进行翻转。
- 如果设置为
-
<flipY>(可选,布尔值,默认为false)- 如果设置为
true,则在加载时沿 Y 轴翻转图片。 - 重要提示: 对于多子图图片,翻转操作是在图片被切分之后进行的。
defName_0始终代表翻转前的图片左上角子图。这意味着先进行裁剪,再对每个子图进行翻转。
- 如果设置为
引用方式
- 当其他定义需要引用某个图片资源时:
defName: 始终代表完整图片(无论是否被切分)。defName_编号: (例如myImage_0,myImage_5) 引用对应的子图。
示例
示例 1:定义一张单图图片
<Define>
<ImageDef>
<defName>PlayerSprite</defName>
<label>玩家角色图片</label>
<description>用于绘制玩家角色的基本图片。</description>
<path>Textures/Player/player_base.png</path>
<pixelsPerUnit>32</pixelsPerUnit>
<flipX>false</flipX>
<flipY>false</flipY>
</ImageDef>
</Define>
在其他定义中引用此图片:
- 引用完整图片:
PlayerSprite
示例 2:定义一张切分后的图片集
假设 enemy_sheet.png 是一张 128x64 像素的图集,包含 4x2 共 8 个子图。
<Define>
<ImageDef>
<defName>EnemySprites</defName>
<label>敌人动画图集</label>
<description>包含敌人的行走和攻击动画帧。</description>
<path>res:Sprites/Enemies/enemy_sheet.png</path>
<wCount>4</wCount>
<hCount>2</hCount>
<pixelsPerUnit>16</pixelsPerUnit>
</ImageDef>
</Define>
- 引用完整图集:
EnemySprites - 引用第一个子图(左上角):
EnemySprites_0 - 引用第二个子图:
EnemySprites_1 - 引用第五个子图(第二行第一个):
EnemySprites_4
示例 3:定义一张来自其他包的图片并翻转加载
<Define>
<ImageDef>
<defName>FlippedBackground</defName>
<label>翻转的背景图</label>
<description>从UI包加载并水平翻转的背景图片。</description>
<path>UIPack:Backgrounds/main_bg.jpg</path>
<wCount>1</wCount>
<hCount>1</hCount>
<pixelsPerUnit>100</pixelsPerUnit>
<flipX>true</flipX>
</ImageDef>
</Define>
在其他定义中引用此图片:
- 引用完整图片:
FlippedBackground
注意事项
- 图片切分与翻转的顺序: 务必记住,
flipX和flipY操作是在wCount和hCount切分操作之后进行的。这意味着即使图片被翻转,defName_0始终指向原始图片(未翻转前)的左上角子图,然后该子图才会被独立翻转。 - 像素整除性: 确保您的图片尺寸可以被
wCount和hCount整除,否则切分可能不会按预期工作或导致错误。 - 路径前缀优先级:
res:前缀的解析优先级最高,其次是包 ID 前缀,最后是当前包。 defName唯一性: 强烈建议所有<ImageDef>的defName都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的defName,后加载的定义将会覆盖先加载的。- 匿名定义: 当
ImageDef作为其他定义的内部结构使用时,defName可以省略,此时它将作为一个匿名的、局部可用的图片定义。在这种情况下,该图片无法通过名称在外部引用。
定义音频资源
在游戏配置文件中,您可以使用 <AudioDef> 元素来定义音频资源。每个 <AudioDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<AudioDef> 用于加载和配置游戏所需的各种音频资源,例如背景音乐、音效、语音等。您可以通过它指定音频文件的存储路径。
参数说明
所有的参数都必须通过嵌套元素的方式进行赋值。
-
<defName>(必需,字符串)- 该音频定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该音频定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该音频定义的具体内容或特殊用途。
-
<path>(必需,字符串)- 指定音频资源的实际存储路径。
- 路径前缀约定:
otherPackID:相对地址: 表示加载otherPackID包下的相对路径音频资源。- 空前缀: 表示加载当前定义所在包的相对路径音频资源。
res:相对地址: 表示加载游戏编译过程中,项目Resources文件夹下的音频资源。res:前缀的优先级高于包 ID 前缀。
引用方式
- 当其他定义需要引用某个音频资源时,始终使用该音频定义的
defName。
示例
示例 1:定义背景音乐
<Define>
<AudioDef>
<defName>BackgroundMusic_MainTheme</defName>
<label>主界面背景音乐</label>
<description>应用于游戏主界面的循环背景音乐。</description>
<path>Audio/BGM/main_theme.mp3</path>
</AudioDef>
</Define>
在其他定义中引用此音频:BackgroundMusic_MainTheme
示例 2:定义一个来自 Resources 文件夹的音效
<Define>
<AudioDef>
<defName>UISound_Click</defName>
<label>UI点击音效</label>
<description>用于按钮点击时的反馈音效。</description>
<path>res:Sounds/UI/click.wav</path>
</AudioDef>
</Define>
在其他定义中引用此音频:UISound_Click
示例 3:定义一个来自其他包的语音文件
<Define>
<AudioDef>
<defName>Dialogue_Greeting</defName>
<label>角色欢迎对话</label>
<description>角色首次见面时的语音问候。</description>
<path>DialoguePack:Voice/greet_player.ogg</path>
</AudioDef>
</Define>
在其他定义中引用此音频:Dialogue_Greeting
注意事项
- 路径前缀优先级:
res:前缀的解析优先级最高,其次是包 ID 前缀,最后是当前包。 defName唯一性: 强烈建议所有<AudioDef>的defName都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的defName,后加载的定义将会覆盖先加载的。- 匿名定义: 当
AudioDef作为其他定义的内部结构使用时,defName可以省略,此时它将作为一个匿名的、局部可用的音频定义。在这种情况下,该音频无法通过名称在外部引用。 - 音频格式: 请确保您引用的音频文件格式是游戏引擎支持的格式(例如 .mp3, .wav, .ogg 等)。
XML 使用说明 - 定义属性集
在游戏配置文件中,您可以使用 <AttributesDef> 元素来定义一组角色或物品的属性。每个 <AttributesDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<AttributesDef> 用于封装和定义一系列常见的游戏属性,如生命值、移动速度、攻击力等。这使得在游戏中创建不同类型单位或物品时,可以方便地引用或调整这些基础属性。
参数说明
所有的参数都必须通过嵌套元素的方式进行赋值。
-
<defName>(必需,字符串)- 该属性集定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该属性集定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该属性集定义的具体内容或特殊用途。
-
<health>(可选,整数,默认为10)- 定义实体对象的生命值或耐久度。
-
<moveSpeed>(可选,浮点数,默认为1)- 定义实体对象的移动速度。
-
<attack>(可选,整数,默认为1)- 定义实体对象的攻击力。
-
<defense>(可选,整数,默认为0)- 定义实体对象的防御力。
-
<attackSpeed>(可选,浮点数,默认为2)- 定义实体对象的攻击速度,例如每秒攻击次数或攻击间隔。
-
<attackRange>(可选,浮点数,默认为3)- 定义实体对象的攻击范围。
-
<attackTargetCount>(可选,整数,默认为1)- 定义实体对象每次攻击可以命中的目标数量。
引用方式
- 当其他定义需要引用某个属性集时,始终使用该属性集定义的
defName。
示例
示例 1:定义一个基础敌人属性集
<Define>
<AttributesDef>
<defName>BasicEnemyAttributes</defName>
<label>基础敌人属性</label>
<description>小型敌人的默认属性配置。</description>
<health>50</health>
<moveSpeed>1.5</moveSpeed>
<attack>10</attack>
<defense>2</defense>
<attackSpeed>1.8</attackSpeed>
<attackRange>2.5</attackRange>
<attackTargetCount>1</attackTargetCount>
</AttributesDef>
</Define>
在其他定义中引用此属性集:BasicEnemyAttributes
示例 2:定义一个防御塔的属性集
<Define>
<AttributesDef>
<defName>DefenseTowerAttributes</defName>
<label>防御塔属性</label>
<description>用于炮塔的属性配置。</description>
<health>200</health>
<moveSpeed>0</moveSpeed> <!-- 塔不能移动 -->
<attack>25</attack>
<defense>10</defense>
<attackSpeed>1.0</attackSpeed>
<attackRange>7.0</attackRange>
<attackTargetCount>1</attackTargetCount>
</AttributesDef>
</Define>
在其他定义中引用此属性集:DefenseTowerAttributes
示例 3:在另一个定义中以内联方式定义属性集(匿名定义)
某些情况下,当一个属性集只在特定位置使用,且不需要全局引用时,可以作为另一个定义的子元素进行匿名定义,此时 <defName> 可省略。
<Define>
<UnitDef>
<defName>SpecialBossUnit</defName>
<sprite>BossImage</sprite>
<baseAttributes><!-- 匿名定义,没有 defName -->
<health>1000</health>
<moveSpeed>0.8</moveSpeed>
<attack>50</attack>
<defense>20</defense>
<attackSpeed>0.5</attackSpeed>
<attackRange>4.0</attackRange>
<attackTargetCount>3</attackTargetCount>
</baseAttributes>
</UnitDef>
</Define>
在此示例中,<AttributesDef> 没有 defName,它的属性只供 SpecialBossUnit 使用。
注意事项
defName唯一性: 强烈建议所有<AttributesDef>的defName都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的defName,后加载的定义将会覆盖先加载的。- 匿名定义: 当
<AttributesDef>作为其他定义的内部结构使用时,defName可以省略,此时它将作为一个匿名的、局部可用的属性集定义。在这种情况下,该属性集无法通过名称在外部引用。 - 默认值: 如果某个属性未在 XML 中明确定义,它将使用其默认值。在设计属性集时,可以只指定需要修改的属性,其他属性将沿用默认值。
XML 使用说明 - 定义行为树
在游戏配置文件中,您可以使用 <BehaviorTreeDef> 元素来定义角色的行为树逻辑。每个 <BehaviorTreeDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<BehaviorTreeDef> 用于构建复杂的AI行为逻辑,通过树状结构组织一系列行为节点。每个节点代表一个决策或行动,它们可以嵌套形成复杂的判断和执行流程。行为树支持多种定义方式,包括传统定义和更简洁的节点定义。行为树的根节点默认是 ThinkNode_Selector。
参数说明
所有的参数都必须通过嵌套元素的方式进行赋值。
-
<defName>(必需,字符串)- 该行为树定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该行为树定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该行为树定义的具体内容或特殊用途。
-
<childTree>(可选,行为树数组)- 包含当前行为树节点的子节点列表。每个子节点本身也是一个
<BehaviorTreeDef>。 - 数组的定义方式为
<childTree><li>元素1</li><li>元素2</li></childTree>。<li>元素本身会被忽略。
- 包含当前行为树节点的子节点列表。每个子节点本身也是一个
-
<className>(可选,字符串,默认为"ThinkNode_Selector")- 指定当前行为树 根节点 所使用的类名。如果省略,则默认为
ThinkNode_Selector。这些类是预定义好的行为节点类型,例如ThinkNode_Selector、ThinkNode_Sequence、JobNode_AttackTarget等。具体的可用类名将在下方“行为树节点类型”部分详细介绍。
- 指定当前行为树 根节点 所使用的类名。如果省略,则默认为
-
<value>(可选,字符串)- 某些行为树类需要初始化参数,
value元素用于提供这些参数。例如,条件判断节点可能需要一个函数调用的字符串作为判断依据。当<value>用于根节点时,它将作为根节点的初始化参数。
- 某些行为树类需要初始化参数,
特殊初始化方式 —— 使用 <Node> 元素
为了使行为树的定义更加简洁直观,当 <BehaviorTreeDef> 作为父级时,其子节点可以直接使用 <Node> 元素进行定义。
Node 元素参数说明:
className(属性,字符串)- 直接作为
<Node>元素的属性指定子节点的类名。
- 直接作为
value(属性,字符串)- 直接作为
<Node>元素的属性指定子节点的初始化参数。
- 直接作为
引用方式和匿名定义
行为树的子节点可以通过两种方式定义:
-
简便的匿名定义 (不支持引用)
- 直接在
<BehaviorTreeDef>内部或者其他<Node>元素下嵌套另一个<Node>元素来定义子节点。 - 这种方式下,子节点没有
defName,只能作为当前父节点的直接子级使用,无法被其他行为树定义引用。 - 语法:
<Node className="子节点类名" value="子节点参数"> <!-- 更多嵌套 Node 元素 --> </Node>
- 直接在
-
传统匿名定义 (支持引用)
- 在
<childTree>元素内使用<li>元素包裹一个完整的<BehaviorTreeDef>结构。 - 这种方式下,子节点可以拥有
defName,从而允许其他行为树定义引用它。当引用一个已命名的行为树定义作为子节点时,可以直接在<li>中放置被引用行为树的defName。 - 语法:
- 匿名子节点:
<childTree> <li> <className>子节点类名</className> <value>子节点参数</value> <childTree> <!-- ... 更多子节点 ... --> </childTree> </li> </childTree> - 引用命名子节点:
<childTree> <li>引用行为树的defName</li> </childTree>
- 匿名子节点:
- 在
行为树节点类型
以下是当前可用的行为树节点类型:
ThinkNode_Selector: 选择节点。会不断从上到下尝试执行其子节点,直到某个子节点返回成功后,该选择节点重置并再次从第一个子节点开始判断。如果所有子节点都返回失败,则此选择节点返回失败。ThinkNode_Sequence: 顺序节点。按顺序从上到下执行子节点。如果任何一个子节点返回失败,则此顺序节点重置并返回失败。只有所有子节点都成功执行后,此顺序节点才返回成功。ThinkNode_Conditional: 条件节点。当其value中定义的条件满足(返回true)时,它会像一个ThinkNode_Selector一样执行其子节点;否则返回失败。ThinkNode_Branch: 分支节点。需要定义2到3个子节点。当第一个子节点返回true时,执行第二个子节点;否则,如果第三个子节点存在,则执行第三个子节点。如果子节点不足2个,则该分支节点总是返回失败。ConstantNode_Failure: 常量节点。总是返回失败状态。ConstantNode_Running: 常量节点。总是返回运行中状态。ConstantNode_Success: 常量节点。总是返回成功状态。JobNode_XXX: 工作节点。所有实际执行具体动作的叶节点都以JobNode_为前缀。例如:JobNode_MoveToAttackRange: 移动到攻击范围。JobNode_AttackTarget: 攻击目标。JobNode_Wander: 随机游荡。JobNode_Idle: 空闲。- 注意: 具体的
JobNode_类型会根据游戏功能而定,请查阅相关文档获取完整列表。
示例
示例 1:使用 <Node> 元素的简便匿名定义
这是一个典型的怪物行为树,根节点使用默认的 ThinkNode_Selector。
<Define>
<BehaviorTreeDef>
<defName>BasicMonsterBehavior</defName>
<label>基本怪物行为</label>
<description>定义了怪物在不同情况下的行为逻辑。</description>
<!-- 根节点默认是 ThinkNode_Selector -->
<Node className="ThinkNode_Conditional" value="HasEnemyInSight()"> <!-- 子节点1:条件 -->
<Node className="ThinkNode_Sequence"> <!-- 条件满足时执行的序列 -->
<Node className="ThinkNode_Conditional" value="HasWeapon()"> <!-- 更深一层的条件 -->
<Node className="JobNode_MoveToAttackRange"/> <!-- 行为:移动到攻击范围 -->
<Node className="JobNode_AttackTarget"/> <!-- 行为:攻击目标 -->
</Node>
<Node className="JobNode_FleeJob"/> <!-- 如果有敌人但没有武器,则逃跑 -->
</Node>
</Node>
<Node className="ThinkNode_Sequence"> <!-- 子节点2:游荡和空闲 -->
<Node className="JobNode_Wander"/> <!-- 行为:随机游荡 -->
<Node className="JobNode_Idle"/> <!-- 行为:空闲 -->
</Node>
</BehaviorTreeDef>
</Define>
示例 2:修改根节点的工作类,并使用传统匿名定义方式 (支持引用)
这个示例展示了如何修改根节点的工作类为 ThinkNode_Sequence,并展示了如何引用一个预定义的子行为树。
假设我们有一个预定义的行为树叫做 AttackLogic:
<Define>
<BehaviorTreeDef>
<defName>AttackLogic</defName>
<label>攻击逻辑</label>
<className>ThinkNode_Sequence</className>
<childTree>
<li>
<className>JobNode_MoveToAttackRange</className>
</li>
<li>
<className>JobNode_AttackTarget</className>
</li>
</childTree>
</BehaviorTreeDef>
</Define>
现在,我们可以在另一个行为树中引用这个 AttackLogic,并自定义根节点类型:
<Define>
<BehaviorTreeDef>
<defName>AdvancedMonsterBehavior</defName>
<label>进阶怪物行为</label>
<description>定义了更复杂的怪物行为树,根节点为序列。</description>
<className>ThinkNode_Sequence</className> <!-- 将根节点指定为 ThinkNode_Sequence -->
<childTree>
<li> <!-- 顺序节点1:检查敌人并决定攻击或逃跑 -->
<className>ThinkNode_Conditional</className>
<value>HasEnemyInSight()</value>
<childTree>
<li> <!-- 在有敌人且有武器的情况下执行攻击逻辑,否则逃跑 -->
<className>ThinkNode_Branch</className>
<li> <className>ThinkNode_Conditional</className><value>HasWeapon()</value> </li> <!-- 条件:是否有武器 -->
<li>AttackLogic</li> <!-- 引用已定义的 AttackLogic 行为树 -->
<li> <className>JobNode_FleeJob</className> </li> <!-- 否则逃跑 -->
</li>
</childTree>
</li>
<li> <!-- 顺序节点2:如果上层成功,则随后进行游荡和空闲 -->
<className>ThinkNode_Sequence</className>
<childTree>
<li>
<className>JobNode_Wander</className>
</li>
<li>
<className>JobNode_Idle</className>
</li>
</childTree>
</li>
</childTree>
</BehaviorTreeDef>
</Define>
在上述示例中,<li>AttackLogic</li> 直接引用了之前使用 defName 定义的 AttackLogic 行为树。
注意事项
- 根节点的定义:
<BehaviorTreeDef>自身的<className>和<value>用于定义整个行为树的根节点。如果未指定<className>,则根节点默认为ThinkNode_Selector。 defName唯一性:defName应该在同类型(BehaviorTreeDef)的全局范围内保持唯一。如果定义了同名的defName,后加载的定义会覆盖先加载的。- 匿名定义与引用: 如果行为树子节点不需要被重用或在其他地方引用,简便的
<Node>嵌套方式更简洁。如果子行为树可能被多个父行为树引用,或者需要更清晰的模块化结构,应使用带有defName的传统定义方式。 - 类名可用性:
<className>中指定的类名必须是游戏代码中实际存在的行为树节点类。请查阅最新的游戏API文档或相关开发指南获取可用类名的详细列表。 ThinkNode_Branch子节点数量:ThinkNode_Branch节点要求至少有两个子节点才能正常工作(条件和执行体)。如果只有2个子节点,则当条件不满足时,该节点表现为失败。如果定义了3个子节点,则第一个子节点为条件,第二个为条件满足时执行,第三个为条件不满足时执行。如果子节点不足2个,ThinkNode_Branch总是返回失败。
XML 使用说明 - 定义绘制结构树
在游戏配置文件中,您可以使用 <DrawNodeDef> 元素来定义复杂的绘制结构树。每个 <DrawNodeDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<DrawNodeDef> 用于构建游戏对象的视觉表现结构,可以组合多个纹理和子节点来形成复杂的身体结构、动画序列或可动部件。它支持纹理引用、节点定位和动画帧率设置。
参数说明
绝大多数参数都必须通过嵌套元素的方式进行赋值。nodeName、position 和 FPS 允许在属性栏定义,这是为了方便紧凑的结构定义。
-
<defName>(必需,字符串)- 该绘制结构定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该绘制结构定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该绘制结构定义的具体内容或特殊用途。
-
<textures>(可选,字符串数组)- 一个字符串数组,包含对
ImageDef的引用。这些引用可以是完整的ImageDef的defName,也可以是其子图的defName_编号。 - 数组的定义方式为
<textures><li>元素1</li><li>元素2</li></textures>。<li>元素本身会被忽略。
- 一个字符串数组,包含对
-
<nodes>(可选,绘制节点数组)- 一个
DrawNodeDef数组,包含当前绘制结构树的子节点。每个子节点本身也是一个<DrawNodeDef>,可以进一步定义其自身的纹理、位置和子节点。 - 数组的定义方式为
<nodes><li>元素1</li><li>元素2</li></nodes>。<li>元素本身会被忽略。
- 一个
-
nodeName(属性,字符串)- 定义当前绘制节点的名称。此名称可用于在代码中标识或操作特定的绘制节点。允许在属性栏定义。
-
position(属性,Vector2类型,默认为(0, 0))- 定义当前绘制节点相对于其父节点的位置偏移。此参数只能在属性栏定义。
- 定义语法:
- 位置值必须用括号
()、方括号[]或不带包裹符号的形式表示。 - 两个坐标之间可以用空格
、逗号,或分号;分隔。
- 位置值必须用括号
- 例如:
position="[1.5, -2]",position="(5; 10)",position="3 4.5"。
-
FPS(属性,浮点数,默认为5f)- 当
textures数组中包含多个纹理时,此参数定义纹理之间切换的帧率(每秒帧数),用于创建动画。允许在属性栏定义。
- 当
引用方式和匿名定义
-
引用
ImageDef: 在<textures>数组中,您可以使用ImageDef的defName来引用完整的图片,或者使用defName_编号来引用图片切分后的特定子图。 -
引用
DrawNodeDef: 在<nodes>数组中,您可以引用其他已定义的<DrawNodeDef>,或者进行匿名定义。- 引用已命名定义: 直接在
<li>元素中放置被引用DrawNodeDef的defName。 - 匿名定义: 直接在
<li>元素中定义子DrawNodeDef的所有属性和子元素。<li>元素同时作为类型说明符和匿名定义的载体。
- 引用已命名定义: 直接在
示例
示例 1:定义一个静态的身体区域(头部),包含单个纹理
<Define>
<DrawNodeDef defName="HumanoidHead" nodeName="Head" position="[0, 1.5]">
<label>人形生物头部</label>
<description>定义了人形生物的头部结构,包含其纹理。</description>
<textures>
<li>HeadTexture</li> <!-- 假设 HeadTexture 是一个已定义的 ImageDef -->
</textures>
</DrawNodeDef>
</Define>
示例 2:定义一个具有动画的腿部,并作为另一个绘制节点的子节点
假设我们有一个 LegAnimationImage 的 ImageDef,它被切分成了多个子图(例如 LegAnimationImage_0、LegAnimationImage_1 等)。
<Define>
<DrawNodeDef defName="HumanoidLeg" nodeName="LeftLeg" position="[-0.5, -1]" FPS="8.0">
<label>人形生物左腿</label>
<description>定义了人形生物的左腿,包含一个简单的行走动画。</description>
<textures>
<li>LegAnimationImage_0</li>
<li>LegAnimationImage_1</li>
<li>LegAnimationImage_2</li>
<!-- ...更多动画帧... -->
</textures>
</DrawNodeDef>
<DrawNodeDef defName="HumanoidBody" nodeName="Body" position="[0, 0]">
<label>人形生物身体</label>
<description>定义了人形生物的身体部分。</description>
<textures>
<li>BodyTexture</li>
</textures>
<nodes>
<li>HumanoidLeg</li> <!-- 引用已定义的 HumanoidLeg -->
<li> <!-- 匿名定义右腿:直接在 <li> 标签中定义其属性和子元素 -->
<textures>
<li>LegAnimationImage_0</li>
<li>LegAnimationImage_1</li>
<li>LegAnimationImage_2</li>
</textures>
<nodeName>RightLeg</nodeName>
<position>[0.5, -1]</position>
<FPS>8.0</FPS>
</li>
</nodes>
</DrawNodeDef>
</Define>
示例 3:复杂的嵌套绘制结构 (已修正匿名定义格式)
<Define>
<DrawNodeDef defName="PlayerCharacter" nodeName="Root" position="[0,0]">
<label>玩家角色绘制</label>
<description>定义了玩家角色的完整绘制结构。</description>
<textures>
<li>BasePelvisTexture</li>
</textures>
<nodes>
<li>HumanoidHead</li> <!-- 引用示例1中的头部 -->
<li>HumanoidBody</li> <!-- 引用示例2中的身体 -->
<li> <!-- 匿名定义一个武器节点 -->
<nodeName>WeaponHand</nodeName>
<position>[0.8, -0.2]</position>
<textures>
<li>SwordTexture</li>
</textures>
<nodes>
<li> <!-- 匿名定义武器尖端节点 -->
<nodeName>WeaponTip</nodeName>
<position>[0.5, 0]</position>
<!-- 只有位置,没有纹理 -->
</li>
</nodes>
</li>
</nodes>
</DrawNodeDef>
</Define>
复杂参数:position 属性定义
position 参数是一个 Vector2 类型,它只能通过属性的方式在 DrawNodeDef 标签中进行定义。其语法具有一定的灵活性。
语法规则:
- 包裹符号: 可以使用
()(括号)、[](方括号) 包裹 x 和 y 坐标,或者完全不使用包裹符号。 - 分隔符: x 和 y 坐标之间可以使用空格
、逗号,或分号;进行分隔。
常见示例:
- 无包裹,空格分隔:
position="1.5 -2.0" - 无包裹,逗号分隔:
position="1.5,-2.0" - 无包裹,分号分隔:
position="1.5;-2.0" - 括号包裹,逗号分隔:
position="(1.5, -2.0)" - 方括号包裹,分号分隔:
position="[1.5; -2.0]" - 整数值:
position="10 5" - 浮点数:
position="0.5 0.5"
注意事项:
当定义 position 时,请确保只在 DrawNodeDef 标签的属性部分进行定义,或者在数组中进行匿名定义时,作为 <li> 元素的属性进行定义。不要尝试通过 <position> 元素来定义,因为 Vector2 不是 Define 的子类,不支持元素定义方式。
XML 使用说明 - 定义绘制顺序集
在游戏配置文件中,您可以使用 <DrawingOrderDef> 元素来定义一个实体在不同状态和朝向下的绘制节点集合。每个 <DrawingOrderDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<DrawingOrderDef> 用于为游戏中的实体(如角色、单位)提供一套完整的、基于状态和朝向的视觉表现配置。它允许您为实体的“闲置”、“行走”、“近战攻击”、“远程攻击”和“死亡”等行为,以及“向上”、“向下”、“向左”、“向右”等朝向,指定不同的绘制结构 (DrawNodeDef)。这使得实体的行为和动画能够无缝地与视觉呈现相结合。
参数说明
所有的参数都必须通过嵌套元素的方式进行赋值。每个参数都期望一个 <DrawNodeDef> 引用或匿名定义,用于描述该特定状态和朝向下的绘制内容。
-
<defName>(必需,字符串)- 该绘制顺序集定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该绘制顺序集定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该绘制顺序集的具体内容或特殊用途。
-
闲置状态(Idle States)
<idle_down>:实体向下(前方)闲置时的绘制节点。<idle_up>:实体向上(后方)闲置时的绘制节点。<idle_left>:实体向左闲置时的绘制节点。<idle_right>:实体向右闲置时的绘制节点。
-
行走状态(Walk States)
<walk_down>:实体向下行走时的绘制节点。<walk_up>:实体向上行走时的绘制节点。<walk_left>:实体向左行走时的绘制节点。<walk_right>:实体向右行走时的绘制节点。
-
近战攻击状态(Melee Attack States)
<meleeAttack_down>:实体向下近战攻击时的绘制节点。<meleeAttack_up>:实体向上近战攻击时的绘制节点。<meleeAttack_left>:实体向左近战攻击时的绘制节点。<meleeAttack_right>:实体向右近战攻击时的绘制节点。
-
远程攻击状态(Ranged Attack States)
<rangedAttack_down>:实体向下远程攻击时的绘制节点。<rangedAttack_up>:实体向上远程攻击时的绘制节点。<rangedAttack_left>:实体向左远程攻击时的绘制节点。<rangedAttack_right>:实体向右远程攻击时的绘制节点。
-
死亡状态(Death States)
<death_down>:实体向下死亡时的绘制节点。<death_up>:实体向上死亡时的绘制节点。<death_left>:实体向左死亡时的绘制节点。<death_right>:实体向右死亡时的绘制节点。
缺项替换机制
为了减少重复定义,<DrawingOrderDef> 内置了缺项替换机制。当某个特定的状态和朝向没有被明确定义时,系统会尝试寻找最接近的替代项。替换规则遵循以下优先级:
- 同一类别内替换: 替换不会跨越不同的行为类别(例如,
idle_down不会替换walk_down)。 - 左右优先互相替换: 如果
_left或_right方向缺失,系统会优先使用同类别下的另一个左右方向。例如,如果idle_left缺失,会尝试使用idle_right。 - 上下优先互相替换: 如果
_up或_down方向缺失,系统会优先使用同类别下的另一个上下方向。例如,如果idle_up缺失,会尝试使用idle_down。
引用方式
- 当其他定义(例如角色定义)需要使用这套绘制动画时,始终使用该绘制顺序集定义的
defName。
示例
示例 1:一个完整的角色绘制顺序集定义
<Define>
<!-- 假设 Character_Maid_Walk_0 到 Character_Maid_Walk_38 等 ImageDef 已经存在 -->
<DrawingOrderDef>
<defName>MaidDrawingOrder</defName>
<label>女仆角色绘制顺序</label>
<description>包含所有方向和状态的动画。</description>
<!-- 闲置状态 -->
<idle_up>
<textures>
<li>Character_Maid_Walk_37</li> <!-- 引用 ImageDef -->
</textures>
</idle_up>
<idle_down>
<textures>
<li>Character_Maid_Walk_1</li>
</textures>
</idle_down>
<idle_left>
<textures>
<li>Character_Maid_Walk_13</li>
</textures>
</idle_left>
<idle_right>
<textures>
<li>Character_Maid_Walk_25</li>
</textures>
</idle_right>
<!-- 行走状态 (动画) -->
<walk_up>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_36</li>
<li>Character_Maid_Walk_37</li>
<li>Character_Maid_Walk_38</li>
<li>Character_Maid_Walk_37</li>
</textures>
</walk_up>
<walk_down>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_0</li>
<li>Character_Maid_Walk_1</li>
<li>Character_Maid_Walk_2</li>
<li>Character_Maid_Walk_1</li>
</textures>
</walk_down>
<walk_left>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_12</li>
<li>Character_Maid_Walk_13</li>
<li>Character_Maid_Walk_14</li>
<li>Character_Maid_Walk_13</li>
</textures>
</walk_left>
<walk_right>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_24</li>
<li>Character_Maid_Walk_25</li>
<li>Character_Maid_Walk_26</li>
<li>Character_Maid_Walk_25</li>
</textures>
</walk_right>
<!-- 近战攻击状态 (动画帧,假设testPawn_2,6,10,14是单帧或动画的第一帧) -->
<meleeAttack_up>
<textures>
<li>testPawn_2</li>
</textures>
</meleeAttack_up>
<meleeAttack_down>
<textures>
<li>testPawn_6</li>
</textures>
</meleeAttack_down>
<meleeAttack_left>
<textures>
<li>testPawn_10</li>
</textures>
</meleeAttack_left>
<meleeAttack_right>
<textures>
<li>testPawn_14</li>
</textures>
</meleeAttack_right>
<!-- 远程攻击状态 -->
<rangedAttack_up>
<textures>
<li>testPawn_3</li>
</textures>
</rangedAttack_up>
<rangedAttack_down>
<textures>
<li>testPawn_7</li>
</textures>
</rangedAttack_down>
<rangedAttack_left>
<textures>
<li>testPawn_11</li>
</textures>
</rangedAttack_left>
<rangedAttack_right>
<textures>
<li>testPawn_15</li>
</textures>
</rangedAttack_right>
<!-- 死亡状态 -->
<death_down>
<textures>
<li>Character_Maid_Death_0</li>
</textures>
<FPS>2.0</FPS>
</death_down>
<!-- 其他死亡方向未定义,将使用 death_down 进行替换 -->
</DrawingOrderDef>
</Define>
在其他定义中引用此绘制顺序集:MaidDrawingOrder
示例 2:利用缺项替换机制的简化定义
<Define>
<DrawingOrderDef>
<defName>SimpleMonsterDrawingOrder</defName>
<label>简易怪物绘制</label>
<!-- 闲置只定义向下和向左,上下、左右会自动替换 -->
<idle_down>
<textures>
<li>Monster_Idle_Front</li>
</textures>
</idle_down>
<idle_left>
<textures>
<li>Monster_Idle_Side</li>
</textures>
</idle_left>
<!-- idle_up 会使用 idle_down -->
<!-- idle_right 会使用 idle_left -->
<!-- 行走只定义向下,所有行走方向都将使用此动画 -->
<walk_down>
<FPS>3.0</FPS>
<textures>
<li>Monster_Walk_Front_0</li>
<li>Monster_Walk_Front_1</li>
</textures>
</walk_down>
<!-- walk_up, walk_left, walk_right 都会使用 walk_down -->
<!-- 死亡只定义向下 -->
<death_down>
<textures>
<li>Monster_Death_0</li>
</textures>
</death_down>
</DrawingOrderDef>
</Define>
此示例展示了如何通过省略部分朝向的定义,利用系统的替换机制来简化配置,尤其适用于那些在不同朝向表现差别不大的实体。
注意事项
defName唯一性: 强烈建议所有<DrawingOrderDef>的defName都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的defName,后加载的定义将会覆盖先加载的。- 匿名定义: 当
<DrawingOrderDef>作为其他定义的内部结构使用时,defName可以省略,此时它将作为一个匿名的、局部可用的绘制顺序集定义。在这种情况下,该绘制顺序集无法通过名称在外部引用。 - DrawNodeDef 的内容: 每个
<DrawingOrderDef>的子元素(如<idle_down>)内部都期望一个<DrawNodeDef>的定义。这个<DrawNodeDef>可以是一个完整的匿名定义(如示例),也可以是一个对已存在的<DrawNodeDef>的引用(如果该字段被设计为允许引用)。在当前示例中,它是一个匿名<DrawNodeDef>。 - 合理利用替换机制: 在设计
DrawingOrderDef时,可以充分利用替换机制来减少 XML 长度,但也要注意不要过度简化,以防视觉表现过于僵硬。对于方向性强的动作(如攻击),通常建议为所有方向提供独特的绘制。
XML 使用说明 - 定义阵营关系
在游戏配置文件中,您可以使用 <AffiliationDef> 元素来定义不同阵营(Affiliation)之间的关系。每个 <AffiliationDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<AffiliationDef> 用于配置游戏中各个阵营(或势力)对于其他阵营的默认态度。通过定义友好、敌对和中立列表,可以构建复杂的势力关系网,影响实体之间的行为逻辑,例如攻击目标选择、协作或互动方式。
参数说明
所有参数都必须通过嵌套元素的方式进行赋值。
-
<defName>(必需,字符串)- 该阵营关系定义的唯一标识符。通常,这会是某个特定阵营的名称。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该阵营关系定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该阵营关系定义的具体内容或特殊用途。
-
<defaultRelation>(可选,枚举类型,默认为Neutral)- 定义本阵营对未在其他列表中明确指定的任何其他阵营的默认关系。
- 可选值包括:
Neutral(中立)Hostile(敌对)Friendly(友好)
-
<hostileFactions>(可选,字符串数组)- 一个字符串数组,列出本阵营视为敌对的其他阵营的
defName。 - 数组的定义方式为
<hostileFactions><li>阵营1defName</li><li>阵营2defName</li></hostileFactions>。<li>元素本身会被忽略。
- 一个字符串数组,列出本阵营视为敌对的其他阵营的
-
<neutralFactions>(可选,字符串数组)- 一个字符串数组,列出本阵营视为中立的其他阵营的
defName。 - 数组的定义方式为
<neutralFactions><li>阵营1defName</li><li>阵营2defName</li></neutralFactions>。<li>元素本身会被忽略。
- 一个字符串数组,列出本阵营视为中立的其他阵营的
-
<friendlyFactions>(可选,字符串数组)- 一个字符串数组,列出本阵营视为友好的其他阵营的
defName。 - 数组的定义方式为
<friendlyFactions><li>阵营1defName</li><li>阵营2defName</li></friendlyFactions>。<li>元素本身会被忽略。
- 一个字符串数组,列出本阵营视为友好的其他阵营的
关系冲突与优先级
当一个目标阵营同时出现在多个关系列表中时(例如,既在 hostileFactions 又在 friendlyFactions 中),系统会根据预设的优先级规则来解决冲突,以确定最终的关系。
优先级顺序(从高到低):
Friendly(友好)Hostile(敌对)Neutral(中立)
这意味着,如果一个阵营在 friendlyFactions 和 hostileFactions 都被列出,它最终会被判定为 Friendly。只有当一个阵营未在任何特定列表中被提及,才会回落到 defaultRelation 定义的关系。
示例
示例 1:定义“Player”阵营的关系
<Define>
<AffiliationDef defName="PlayerAffiliation">
<label>玩家阵营</label>
<description>玩家及其盟友的阵营。</description>
<defaultRelation>Neutral</defaultRelation> <!-- 默认对所有未指定者中立 -->
<hostileFactions>
<li>MonsterAffiliation</li> <!-- 对 MonsterAffiliation 敌对 -->
<li>BanditAffiliation</li> <!-- 对 BanditAffiliation 敌对 -->
</hostileFactions>
<friendlyFactions>
<li>AllyAffiliation</li> <!-- 对 AllyAffiliation 友好 -->
</friendlyFactions>
<neutralFactions>
<!-- 没有特别指定的,因为 defaultRelation 已经是 Neutral -->
<!-- 假设将来可能某个阵营默认是Friendly,但这里想设置为Neutral,就可以在这里列出 -->
<li>WildLifeAffiliation</li>
</neutralFactions>
</AffiliationDef>
</Define>
示例 2:利用优先级规则的定义
假设我们希望 SomeTroubledFaction 对 PlayerAffiliation 友好,但由于配置失误,它也被列入了 hostileFactions。
<Define>
<AffiliationDef defName="SomeTroubledFaction">
<label>麻烦的阵营</label>
<description>一个关系复杂的阵营。</description>
<defaultRelation>Neutral</defaultRelation>
<friendlyFactions>
<li>PlayerAffiliation</li> <!-- 明确对玩家友好 -->
</friendlyFactions>
<hostileFactions>
<li>PlayerAffiliation</li> <!-- 错误地将玩家也列为敌对 -->
</hostileFactions>
</AffiliationDef>
</Define>
在此示例中,尽管 PlayerAffiliation 同时出现在 friendlyFactions 和 hostileFactions 中,但由于 友好(Friendly)关系优先级高于敌对(Hostile),SomeTroubledFaction 最终会视为 PlayerAffiliation 为 友好 阵营。
示例 3:仅定义敌对关系,其他默认为中立
<Define>
<AffiliationDef defName="MonsterAffiliation">
<label>怪物阵营</label>
<description>对所有非同类阵营都敌对。</description>
<defaultRelation>Hostile</defaultRelation> <!-- 假设怪物对所有未明确的都敌对 -->
<friendlyFactions>
<li>MonsterAffiliation</li> <!-- 对自己(同类)友好 -->
</friendlyFactions>
<!-- 不需要定义 hostileFactions,因为 defaultRelation 已经是 Hostile -->
</AffiliationDef>
</Define>
注意事项
defName唯一性:AffiliationDef的defName通常应与游戏中实际存在的阵营ID或名称保持一致,并确保其全局唯一性。- 双向关系: 阵营关系默认是单向的。如果
A阵营将B视为Friendly,不代表B阵营也自动将A视为Friendly。您需要在B阵营的AffiliationDef中单独配置其对A的关系。 - 列表内容:
hostileFactions、neutralFactions和friendlyFactions列表中应填入其他AffiliationDef的defName。 - 优先级: 务必牢记友好的最高优先级,这在设计关系网时尤为关键,可以避免意外的冲突导致错误的阵营行为。
子弹定义 (<BulletDef>)
功能说明
子弹定义主要用于描述游戏中的投射物或子弹的特性。这些定义通常由远程武器引用,以指定武器发射物的行为、外观和属性。子弹不仅包含基本的名称和描述,还能够定义自身的移动速度、生命值等属性,以及在不同状态下显示的纹理。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该子弹定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该子弹在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该子弹在游戏中的详细描述。 |
attributes | 定义 | (匿名定义默认值) | 定义子弹具体的战斗属性,如生命值、移动速度等。可以是引用或匿名定义。详见下文**attributes 字段**。 |
drawingOrder | 定义 | (空) | 定义子弹在不同状态和方向下的纹理绘制顺序。这是一个匿名嵌套定义。详见下文**drawingOrder 字段**。 |
示例
这是一个定义名为“yellowBullet”的子弹的例子,展示了属性和绘制顺序的嵌套定义:
<Define>
<!-- 子弹纹理定义 -->
<ImageDef>
<defName>yellowBullet</defName>
<path>Resources\Item\YellowBullet_down.png</path>
<pixelsPerUnit>64</pixelsPerUnit>
</ImageDef>
<!-- 子弹定义 -->
<BulletDef>
<defName>yellowBullet</defName>
<label>黄色子弹</label>
<description>一颗黄色的子弹</description>
<!-- 嵌套定义属性 -->
<attributes>
<health>1</health>
<moveSpeed>20</moveSpeed>
<attack>1</attack> <!-- 子弹也可以有自己的攻击力 -->
</attributes>
<!-- 嵌套定义纹理绘制顺序 -->
<drawingOrder>
<!-- 闲置向下状态的纹理 -->
<idle_down>
<textures>
<li>yellowBullet</li>
</textures>
</idle_down>
<!-- 行走向下状态的纹理 -->
<walk_down>
<textures>
<li>yellowBullet</li>
</textures>
</walk_down>
</drawingOrder>
</BulletDef>
</Define>
复杂参数说明
attributes 字段 (子弹属性定义)
- 说明:定义子弹的具体属性,如生命值、移动速度、攻击力等。可以是一个对预定义的
<AttributesDef>的defName引用,也可以是当前位置的匿名定义。 - 引用方式:
<attributes>AttributesDef的defName</attributes> - 匿名定义方式:
<attributes> <health>1</health> <moveSpeed>20</moveSpeed> <attack>1</attack> <defense>0</defense> <attackSpeed>1</attackSpeed> <attackRange>1</attackRange> <attackTargetCount>1</attackTargetCount> </attributes>
drawingOrder 字段 (纹理绘制顺序定义)
- 说明:这是一个匿名嵌套定义,用于指定子弹在不同游戏状态(如
idle_down,walk_down等)下所使用的纹理。drawingOrder下的每个子元素(例如<idle_down>)都代表一个具体的动画状态或方向组,其内部可以定义该状态下的纹理列表。 - 匿名定义方式:
<drawingOrder> <!-- 状态/方向名称 (例如:idle_down) --> <状态名称> <textures> <li>ImageDef的defName1</li> <li>ImageDef的defName2</li> <!-- ...更多纹理引用 --> </textures> <!-- 还可以添加其他与该状态相关的属性 --> </状态名称> <!-- ...可以定义更多状态/方向 --> </drawingOrder> - 示例:
请注意,<drawingOrder> <idle_down> <textures> <li>yellowBullet</li> </textures> </idle_down> <walk_down> <textures> <li>yellowBullet</li> </textures> </walk_down> <!-- 如果子弹有其他方向或动画,可以在此处添加 --> <idle_up> <textures> <li>yellowBullet_up</li> </textures> </idle_up> </drawingOrder><textures>元素中包含的是一系列<li>元素,每个<li>引用一个已定义的<ImageDef>的defName。这种结构使得子弹的动画和显示具有高度的灵活性。
物品定义 (ItemDef)
物品定义用于创建游戏中各种可交互的物品数据。它包含了物品的视觉表现、堆叠行为、稀有度以及可能附带的效果等属性。
参数说明
所有物品定义都必须包含 defName 字段,作为其全局唯一标识。label 和 description 字段是可选的,用于提供更友好的显示名称和详细描述。
-
<defName>- 说明: 物品定义的唯一标识符。
- 类型: 字符串
- 示例:
<defName>basicSword</defName>
-
<label>(可选)- 说明: 物品在游戏内显示的名称。
- 类型: 字符串
- 示例:
<label>新手之剑</label>
-
<description>(可选)- 说明: 物品的详细描述或背景故事。
- 类型: 字符串
- 示例:
<description>一把普通但结实的长剑。</description>
-
<FPS>- 说明: 物品动画的每秒帧数。
- 类型: 浮点数
- 默认值:
3.0 - 示例:
<FPS>6</FPS>
-
<textures>- 说明: 物品使用的纹理定义名列表。这些名称引用了 ImageDef 中已定义的纹理。
- 类型: 字符串数组
- 示例:
<textures> <li>Item_SwordFrame1</li> <li>Item_SwordFrame2</li> </textures>
-
<rarity>- 说明: 物品的稀有度。
- 类型: 枚举
- 可选值:
Common(普通),Uncommon(不寻常),Rare(稀有),Epic(史诗),Legendary(传说) - 默认值:
Common - 示例:
<rarity>Rare</rarity>
-
<maxStack>- 说明: 物品的最大堆叠数量。
- 类型: 整数
- 默认值:
10 - 示例:
<maxStack>99</maxStack>
-
<ssEquippable>- 说明: 物品是否可以被装备。
- 类型: 布尔值
- 默认值:
false - 示例:
<ssEquippable>true</ssEquippable>
-
<hediffs>- 说明: 物品在装备或使用时可能附加的效果列表。每个效果可以是已定义的 HediffDef 引用,也可以是匿名定义。
- 类型: HediffDef 数组
- 默认值: 空
- 示例: 详见下方“复杂参数:
<hediffs>”
示例
<Define>
<defName>healingPotion</defName>
<label>治疗药水</label>
<description>饮用后可以恢复少量生命值。</description>
<FPS>1</FPS>
<textures>
<li>Potion_Red</li>
</textures>
<rarity>Common</rarity>
<maxStack>5</maxStack>
<ssEquippable>false</ssEquippable>
<hediffs>
<li>
<time>5</time> <!-- 效果持续5秒 -->
<stages>
<li>
<start>0</start> <!-- 阶段从0秒开始 -->
<attributesOffset>
<healthOffset>10</healthOffset> <!-- 瞬间恢复10点生命 -->
</attributesOffset>
</li>
</stages>
</li>
</hediffs>
</Define>
<Define>
<defName>advancedSword</defName>
<label>锋利长剑</label>
<description>一把制作精良的长剑,提供额外攻击力。</description>
<FPS>2</FPS>
<textures>
<li>Sword_Advanced_Frame1</li>
<li>Sword_Advanced_Frame2</li>
</textures>
<rarity>Uncommon</rarity>
<maxStack>1</maxStack>
<ssEquippable>true</ssEquippable>
<hediffs>
<!-- 引用已定义的装备效果 -->
<li>Equip_AttackBoost</li>
</hediffs>
</Define>
复杂参数:<hediffs>
<hediffs> 字段是一个列表,用于定义当物品被使用或装备时所能施加的生命体效果(Hediff)。列表中的每个元素可以是 已注册的 HediffDef 定义名,也可以是 直接嵌套定义的匿名 HediffDef。
<HediffDef> (匿名或引用)
关于 HediffDef 的详细说明请参阅 HediffDef 文档。在此处,当作为匿名定义使用时,其包含以下子字段:
-
<time>- 说明: Hediff 的持续时间(秒)。如果设置为
-1,表示效果永久持续(例如装备效果)。 - 类型: 浮点数
- 默认值:
-1.0 - 示例:
<time>10.5</time>
- 说明: Hediff 的持续时间(秒)。如果设置为
-
<stages>- 说明: Hediff 的发展阶段列表。每个阶段定义了效果在不同持续时间段内的属性修改。
- 类型:
HediffStageDef数组 - 示例: 详见下方
<HediffStageDef>说明。
-
<comps>- 说明: 附加到此 Hediff 的组件列表,用于添加更复杂的行为和逻辑。
- 类型:
HediffCompDef数组 - 示例: 详见下方
<HediffCompDef>说明。
<HediffStageDef> (匿名定义)
HediffStageDef 定义了 Hediff 特定阶段的属性修改。它作为 stages 字段的匿名子元素出现。
-
<start>- 说明: 该阶段开始的时间点(从 Hediff 施加开始计算的秒数)。
- 类型: 浮点数
- 示例:
<start>0</start>(表示从Hediff开始时就进入此阶段)
-
<attributesOffset>- 说明: 该阶段对属性的偏移量定义。这是一个匿名
AttributesOffsetDef。 - 类型:
AttributesOffsetDef - 示例: 详见下方
<AttributesOffsetDef>说明。
- 说明: 该阶段对属性的偏移量定义。这是一个匿名
<AttributesOffsetDef> (匿名定义)
AttributesOffsetDef 用于详细定义对角色属性的各种数值和百分比偏移。它作为 attributesOffset 字段的匿名子元素出现。
-
绝对值偏移 (Added/Subtracted directly)
<healthOffset>: 生命值绝对偏移。<moveSpeedOffset>: 移动速度绝对偏移。<attackOffset>: 攻击力绝对偏移。<defenseOffset>: 防御力绝对偏移。<attackSpeedOffset>: 攻击速度绝对偏移。<attackRangeOffset>: 攻击范围绝对偏移。<attackTargetCountOffset>: 攻击目标数量绝对偏移。- 类型: 浮点数
- 默认值:
0.0 - 示例:
<healthOffset>5</healthOffset>(增加5点生命值)
-
百分比偏移 (Multiplied as a factor)
<healthPercentOffset>: 生命值百分比偏移 (例如0.1表示 +10%)。<moveSpeedPercentOffset>: 移动速度百分比偏移。<attackPercentOffset>: 攻击力百分比偏移。<defensePercentOffset>: 防御力百分比偏移。<attackSpeedPercentOffset>: 攻击速度百分比偏移。<attackRangePercentOffset>: 攻击范围百分比偏移。<attackTargetCountPercentOffset>: 攻击目标数量百分比偏移。- 类型: 浮点数
- 默认值:
0.0 - 示例:
<attackPercentOffset>0.25</attackPercentOffset>(增加25%攻击力)
<HediffCompDef> (匿名定义)
HediffCompDef 定义了附加到 Hediff 上的组件,这些组件提供了除属性修改之外的额外行为。它作为 comps 字段的匿名子元素出现。
-
<compClass>- 说明: 组件的类名,用于在运行时创建对应的组件实例。
- 类型: 字符串
- 示例:
<compClass>HediffComp_HealOverTime</compClass>
-
<properties>- 说明: 组件的初始化属性,通常是一个字符串,其具体格式和内容由
compClass决定。 - 类型: 字符串
- 示例:
<properties>amountPerSecond=1</properties>
- 说明: 组件的初始化属性,通常是一个字符串,其具体格式和内容由
<hediffs> 复杂示例
<hediffs>
<li> <!-- 定义一个持续伤害效果 -->
<time>15</time> <!-- 持续15秒 -->
<label>中毒</label>
<description>持续受到毒素伤害。</description>
<stages>
<li> <!-- 第一个阶段:开始时轻微中毒 -->
<start>0</start>
<attributesOffset>
<healthOffset>-0.5</healthOffset> <!-- 每秒损失0.5生命 -->
<moveSpeedPercentOffset>-0.1</moveSpeedPercentOffset> <!-- 移动速度降低10% -->
</attributesOffset>
</li>
<li> <!-- 第二个阶段:5秒后加重中毒 -->
<start>5</start>
<attributesOffset>
<healthOffset>-1.0</healthOffset> <!-- 每秒损失1.0生命 -->
<moveSpeedPercentOffset>-0.2</moveSpeedPercentOffset>
</attributesOffset>
</li>
</stages>
<comps>
<li> <!-- 附加一个每秒播放中毒动画的组件 -->
<compClass>HediffComp_PlayEffect</compClass>
<properties>effectName=PoisonCloud;interval=1</properties>
</li>
</comps>
</li>
<li> <!-- 引用一个已定义的 HediffDef -->
<defName>Hediff_Regeneration</defName>
</li>
</hediffs>
武器定义 (<WeaponDef>)
功能说明
武器定义用于描述游戏中的各种武器的特性,包括其攻击方式、属性、外观等。武器定义继承了物品定义 (<ItemDef>) 的所有基本特性,因此也拥有物品的通用属性,如堆叠数量、稀有度等。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该武器定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该武器在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该武器在游戏中的详细描述。 |
FPS | 浮点数 | 3 | 定义武器显示动画的帧率。 |
textures | 字符串数组 | (空) | 引用多个 <ImageDef> 的 defName,用于定义武器在世界或UI中的外观纹理。 |
rarity | 字符串 | Common | 定义武器的稀有度。详见下文**rarity 字段**。 |
maxStack | 整数 | 10 | 定义该武器的最大堆叠数量。 |
ssEquippable | 布尔值 | false | 定义该武器是否可被实体装备。 |
type | 字符串 | Melee | 定义武器的攻击类型,可以是“近战”或“远程”。详见下文**type 字段**。 |
attributes | 定义 | (匿名定义默认值) | 定义武器具体的战斗属性,如攻击力、防御力、攻击速度等。可以是引用或匿名定义。详见下文**attributes 字段**。 |
bullet | 定义 | 无 | 仅当 type 为 Ranged 时有效。定义远程武器发射的子弹特性。可以是引用或匿名定义。详见下文**bullet 字段**。 |
attackAnimation | 字符串数组 | (空) | 引用多个动画帧名的字符串数组,用于定义武器攻击时播放的专属动画序列。详见下文**attackAnimation 字段**。 |
attackDetectionTime | 浮点数 | 0 | 攻击判定时间点,表示攻击动画播放到该百分比时触发伤害或投射子弹。取值范围0到1。 |
useEntityAttackAnimation | 布尔值 | true | 是否使用实体自身的攻击动画,如果为 false 则使用武器自带的 attackAnimation。 |
示例
这是一个定义名为“TestGun”的远程武器的例子:
<Define>
<!-- 子弹定义,会被WeaponDef中bullet引用 -->
<BulletDef>
<defName>yellowBullet</defName>
<label>黄色子弹</label>
<description>一颗黄色的子弹</description>
<!-- 嵌套定义属性 -->
<attributes>
<health>1</health>
<moveSpeed>20</moveSpeed>
</attributes>
<!-- 嵌套定义纹理绘制顺序 -->
<drawingOrder>
<idle_down>
<textures>
<li>yellowBullet</li>
</textures>
</idle_down>
<walk_down>
<textures>
<li>yellowBullet</li>
</textures>
</walk_down>
</drawingOrder>
</BulletDef>
<!-- 属性定义,会被WeaponDef中attributes引用 -->
<AttributesDef>
<defName>TestGunAttributes</defName>
<attack>10</attack>
<defense>3</defense>
<attackSpeed>1</attackSpeed>
<attackRange>10</attackRange>
<attackTargetCount>1</attackTargetCount>
</AttributesDef>
<!-- 武器定义 -->
<WeaponDef>
<defName>TestGun</defName>
<label>测试枪</label>
<description>一把测试用的枪</description>
<!-- 引用属性定义 -->
<attributes>TestGunAttributes</attributes>
<type>Ranged</type>
<FPS>10</FPS>
<textures>
<li>TestGunItem</li>
</textures>
<attackAnimation>
<li>testGunAttackAnimation_0</li>
<li>testGunAttackAnimation_1</li>
<li>testGunAttackAnimation_2</li>
<li>testGunAttackAnimation_3</li>
<li>testGunAttackAnimation_4</li>
<li>testGunAttackAnimation_5</li>
<li>testGunAttackAnimation_6</li>
<li>testGunAttackAnimation_7</li>
<li>testGunAttackAnimation_8</li>
<li>testGunAttackAnimation_9</li>
</attackAnimation>
<attackDetectionTime>0.5</attackDetectionTime>
<maxStack>1</maxStack>
<rarity>Uncommon</rarity>
<bullet>yellowBullet</bullet> <!-- 引用子弹定义 -->
</WeaponDef>
</Define>
复杂参数说明
type 字段
- 说明:指定武器的攻击类型。
- 可选值:
Melee(近战武器)Ranged(远程武器)
- 示例:
<type>Ranged</type>
rarity 字段
- 说明:指定该物品的稀有度。
- 可选值:
Common(普通)Uncommon(不常见)Rare(稀有)Epic(史诗)Legendary(传说)
- 示例:
<rarity>Uncommon</rarity>
textures 字段 (图片定义引用数组)
- 说明:用于指定武器在界面或游戏世界中显示的纹理。这是一个字符串数组,每个元素引用一个
<ImageDef>的defName。 - 引用方式:
<textures> <li>ImageDef的defName1</li> <li>ImageDef的defName2</li> <!-- ...更多纹理引用 --> </textures> - 示例:
<textures> <li>TestGunItem</li> </textures>
attackAnimation 字段 (动画帧引用数组)
- 说明:用于指定武器攻击时播放的动画帧序列。这是一个字符串数组,每个元素引用一个
<ImageDef>定义的动画帧。通常,一个动画纹理会在其defName后拼接_0,_1,_2等来表示具体的帧。 - 引用方式:
<attackAnimation> <li>ImageDef动画帧名1</li> <li>ImageDef动画帧名2</li> <!-- ...更多动画帧引用 --> </attackAnimation> - 示例:
<attackAnimation> <li>testGunAttackAnimation_0</li> <li>testGunAttackAnimation_1</li> <!-- ... --> <li>testGunAttackAnimation_9</li> </attackAnimation>
attributes 字段 (武器属性定义)
- 说明:定义武器具体的战斗属性,如生命值、移动速度、攻击力、防御力、攻击速度、攻击范围和攻击目标数量。可以是一个对预定义的
<AttributesDef>的defName引用,也可以是当前位置的匿名定义。 - 引用方式:
<attributes>AttributesDef的defName</attributes> - 匿名定义方式:
<attributes> <health>10</health> <moveSpeed>1</moveSpeed> <attack>1</attack> <defense>0</defense> <attackSpeed>2</attackSpeed> <attackRange>3</attackRange> <attackTargetCount>1</attackTargetCount> </attributes>
bullet 字段 (子弹定义)
- 说明:仅当武器类型为
Ranged时有效,用于定义该武器发射的子弹的特性。可以是一个对预定义的<BulletDef>的defName引用,也可以是当前位置的匿名定义。 - 引用方式:
<bullet>BulletDef的defName</bullet> - 匿名定义方式:
<bullet> <defName>匿名子弹名</defName> <!-- 匿名定义也可选择性声明defName --> <label>匿名子弹</label> <!-- 子弹的属性定义 (匿名定义) --> <attributes> <health>1</health> <moveSpeed>20</moveSpeed> </attributes> <!-- 嵌套定义纹理绘制顺序 (匿名定义) --> <drawingOrder> <idle_down> <textures> <li>yellowBullet</li> </textures> </idle_down> </drawingOrder> <!-- 其他子弹独有属性 --> </bullet>
消息定义 (<MessageDef>)
功能说明
消息定义用于在游戏中创建各种提示文本或通知。通过定义消息,开发者可以控制文本的实际内容、显示类别(例如聊天气泡、屏幕中央大字等)以及文本的颜色,从而实现多样化的游戏内信息交互。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该消息定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该消息的内部标识标签,通常用于编辑器预览。 |
description | 字符串 | (空) | 可选。该消息的详细描述或备注。 |
type | 字符串 | 无 | 必需。定义消息的显示类别,如在实体上方显示或屏幕中央显示。详见下文**type 字段**。 |
text | 字符串 | 无 | 必需。消息的实际文本内容。 |
color | 字符串 | (空) | 可选。消息文本的颜色,使用HTML颜色字符串格式。详见下文**color 字段**。 |
示例
这是一个定义了几种不同显示类别的消息的例子:
<Define>
<MessageDef>
<defName>InteractionHint</defName>
<label>互动提示</label>
<description>在NPC或可互动对象上方显示的简短提示</description>
<type>FocusedEntityOverheadText</type>
<text>按 [E] 互动</text>
<color>#00FF00</color> <!-- 绿色文本 -->
</MessageDef>
<MessageDef>
<defName>DialogueBubble</defName>
<label>对话气泡</label>
<description>NPC说话时显示的聊天气泡</description>
<type>FocusedEntityChatBubble</type>
<text>你好,初次见面!</text>
<color>#FFFFFF</color> <!-- 白色文本 -->
</MessageDef>
<MessageDef>
<defName>QuestComplete</defName>
<label>任务完成通知</label>
<description>任务完成时在屏幕中央显示的大型通知</description>
<type>ScreenCenterLargeText</type>
<text>任务完成!</text>
<color>Gold</color> <!-- 金色文本 -->
</MessageDef>
<MessageDef>
<defName>AmbientHint</defName>
<label>环境提示</label>
<description>右下角浮动的非干扰性提示</description>
<type>PassiveHint</type>
<text>区域发现:神秘森林</text>
<color>LightGray</color> <!-- 浅灰色文本 -->
</MessageDef>
</Define>
复杂参数说明
type 字段 (消息显示类别)
- 说明:定义消息在游戏中的具体显示方式和位置。
- 可选值:
Default: 默认或未分类的显示方式。FocusedEntityChatBubble: 显示在玩家当前焦点实体(如NPC或交互物)上方,以聊天气泡形式呈现。FocusedEntityOverheadText: 显示在玩家当前焦点实体(如NPC或交互物)头顶,通常是简短的状态、名称或互动提示。ScreenCenterLargeText: 大型文本显示在屏幕中央,通常用于重要通知、标题或剧情提示,需要玩家立即注意。PassiveHint: 非焦点提示,通常以不易干扰的方式(如屏幕边缘、HUD小字或右下角浮动)显示,提供辅助信息、次要指引或环境提示。
- 示例:
<type>FocusedEntityOverheadText</type>
color 字段 (文本颜色)
- 说明:定义消息文本的颜色。颜色值必须是有效的HTML颜色字符串,支持多种格式:
- 颜色名称:如 "Red", "Blue", "Green", "Gold", "LightGray" 等。
- 十六进制RGB/RGBA值:
#RRGGBB:例如#FF0000(红色),#00FF00(绿色),#0000FF(蓝色)。#AARRGGBB:例如#80FF0000(半透明红色)。#RGB或#ARGB:例如#F00(红色),#8F00(半透明红色)。
- 示例:
<color>#FF00FF</color> <!-- 紫色文本 --> <color>Blue</color> <!-- 蓝色文本 --> <color>#FFFF0000</color> <!-- 不透明红色文本 -->
XML 使用说明 - 定义通用事件
在游戏配置文件中,您可以使用 <EventDef> 元素来定义各种可触发的游戏事件。每个 <EventDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<EventDef> 提供了一种灵活的机制来定义游戏中各种可执行的事件,从生成实体到触发故事情节。它通过指定一个事件处理类 (workClass) 及其配套的参数 (parameter) 来实现事件的定制化行为。
参数说明
所有参数都必须通过嵌套元素的方式进行赋值。
-
<defName>(必需,字符串)- 该事件定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该事件定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该事件的具体内容或特殊用途。
-
<workClass>(必需,字符串)- 指定处理此事件逻辑的后端类名。此字符串必须精确匹配到游戏中对应的事件处理类。
- 关于
workClass类的详细讲解,请参阅稍后发布的第三章:核心工作类定义。
-
<parameter>(必需,JSON 字符串)- 包含传递给
workClass指定事件处理类的所有必要参数。这些参数必须以JSON (JavaScript Object Notation) 格式提供,并且其结构和内容完全取决于workClass所需的数据。
- 包含传递给
parameter 参数:JSON 格式详解
parameter 参数是一个 JSON 格式的字符串,其内部结构和字段名必须与 workClass 所期望的参数类型严格匹配。游戏引擎会负责解析这个 JSON 字符串,并将其映射到 workClass 内部对应的参数对象上。
JSON 格式的特点:
- 键值对: 由键(字符串)和值组成,键和值之间用冒号
:分隔。 - 对象: 用大括号
{}包裹,包含零个或多个键值对,键值对之间用逗号,分隔。 - 数组: 用方括号
[]包裹,包含零个或多个值,值之间用逗号,分隔。 - 数据类型: 支持字符串、数字、布尔值(true/false)、JSON 对象、JSON 数组和 null。
编写规则:
- 整个 JSON 结构必须是合法的。
- 所有键(字段名)必须用双引号
""包裹。 - 所有字符串值也必须用双引号
""包裹。数字、布尔值不需要。 - JSON 内部可以包含换行符和缩进,以提高可读性,这些空白字符在解析时会被忽略。
示例
示例 1:生成多个怪物事件
此事件定义使用 Event_EntityGenerater 作为工作类,负责在地图外生成指定数量的怪物。parameter JSON 结构清晰地定义了要生成的实体类型、位置类型和数量。
<Define>
<EventDef>
<defName>Event_SpawnMonsterA1_3</defName>
<label>生成3个A1型怪物</label>
<description>在地图外生成3个编号为MonsterA1的怪物。</description>
<workClass>Event_EntityGenerater</workClass>
<parameter>
{
"DefinitionsToChooseFrom":[
{ "DefName":"MonsterA1", "DefTypeName":"MonsterDef" }
],
"LocationType":"OffMap",
"Count":3
}
</parameter>
</EventDef>
</Define>
parameter JSON 结构分析:
- 这是一个 JSON 对象。
"DefinitionsToChooseFrom":一个 JSON 数组,其中每个元素都是一个 JSON 对象,包含要生成的实体的DefName(定义名称)和DefTypeName(定义类型名称)。"LocationType":一个字符串,指定实体生成的位置类型。"Count":一个数字,指定要生成的实体数量。
示例 2:触发特定故事情节事件
此示例展示了一个触发故事情节的事件,parameter 可能包含故事ID、参与者等信息。
<Define>
<EventDef>
<defName>Event_TriggerStory_LostChild</defName>
<label>触发失踪儿童故事</label>
<description>在一个随机地点触发一个关于失踪儿童的故事事件。</description>
<workClass>Event_StoryManager</workClass>
<parameter>
{
"StoryID": "LostChildScenario",
"TriggerLocation": "Random",
"Participants": [
{ "Role": "QuestGiver", "Faction": "PlayerAffiliation" },
{ "Role": "MissingChild", "DefName": "ChildPawnDef", "DefTypeName": "PawnDef" }
]
}
</parameter>
</EventDef>
</Define>
注意事项
parameter的严格性:parameter中的 JSON 结构必须与workClass内部定义的参数类结构完全匹配,包括字段名的大小写和数据类型。任何不匹配都可能导致事件无法正确执行。workClass定义:workClass对应的类必须在游戏中存在且可加载。错误的类名会导致事件无法实例化。- 可读性: 尽管 JSON 允许在一行中定义,但为了配置文件的可读性和易维护性,强烈建议使用多行和缩进来格式化
parameter的内容。
故事定义 (<StoryDef>)
功能说明
故事定义用于组织和编排游戏中的故事情节流程。一个完整的故事由一系列按顺序执行的故事阶段 (<StoryStageDef>) 组成,每个阶段可以包含等待时间、触发特定事件或显示消息等。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该故事定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该故事在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该故事的详细描述。 |
storyStage | 故事阶段数组 | 无 | 必需。定义组成该故事的各个阶段。这是一个故事阶段的数组。详见下文**storyStage 字段**。 |
示例
这是一个定义了一个包含两个阶段的故事的例子:
<Define>
<!-- 独立的事件和消息定义,供故事阶段引用 -->
<EventDef>
<defName>StartQuest_FirstEncounter</defName>
<workClass>Event_StartQuest</workClass>
<parameter>{"QuestId": "FirstEncounter"}</parameter>
</EventDef>
<MessageDef>
<defName>WelcomeMessage</defName>
<type>ScreenCenterLargeText</type>
<text>欢迎来到这个世界!</text>
<color>White</color>
</MessageDef>
<!-- 故事定义 -->
<StoryDef>
<defName>NewGameIntro</defName>
<label>新手引导故事</label>
<description>玩家初次进入游戏时的引导流程。</description>
<storyStage>
<li>
<lastWaitTime>0</lastWaitTime>
<nextWaitTime>3</nextWaitTime> <!-- 等待3秒 -->
<messageDef>WelcomeMessage</messageDef> <!-- 引用消息定义 -->
</li>
<li>
<lastWaitTime>3</lastWaitTime> <!-- 继承上一个阶段的nextWaitTime作为lastWaitTime,也可自定义 -->
<nextWaitTime>0</nextWaitTime>
<eventDef>StartQuest_FirstEncounter</eventDef> <!-- 引用事件定义 -->
</li>
</storyStage>
</StoryDef>
</Define>
故事阶段定义 (<StoryStageDef>)
功能说明
故事阶段定义是构成完整故事的基本单元。每个阶段代表故事流程中的一个步骤,可以指定该阶段的持续时间(通过等待时间)、需要触发的特定事件、以及需要显示给玩家的消息。故事阶段通常作为 <StoryDef> 内部的匿名定义存在。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 可选。该故事阶段的唯一标识符。作为匿名定义时可省略。 |
label | 字符串 | (空) | 可选。该故事阶段的内部标识标签。 |
description | 字符串 | (空) | 可选。该故事阶段的详细描述。 |
lastWaitTime | 浮点数 | 0 | 当前阶段开始前必须等待的前一个阶段的结束时间点(秒)。 |
nextWaitTime | 浮点数 | 0 | 当前阶段结束前需要等待的时间(秒)。这个值通常作为下一个阶段的 lastWaitTime。 |
eventDef | 定义 | 无 | 可选。定义此阶段结束后要触发的事件。可以是预定义事件的引用或匿名定义。详见下文**eventDef 字段**。 |
messageDef | 定义 | 无 | 可选。定义此阶段中要显示给玩家的消息。可以是预定义消息的引用或匿名定义。详见下文**messageDef 字段**。 |
复杂参数说明
storyStage 字段 (故事阶段数组)
- 说明:这是一个数组,其内部每个
<li>元素代表一个故事阶段的定义。通常,这些阶段定义会以匿名方式直接嵌套在<li>中。 - 数组定义方式:
<storyStage> <li> <!-- 第一个故事阶段的定义 --> <lastWaitTime>0</lastWaitTime> <nextWaitTime>5</nextWaitTime> <messageDef> <type>ScreenCenterLargeText</type> <text>开始新篇章!</text> </messageDef> </li> <li> <!-- 第二个故事阶段的定义 --> <lastWaitTime>5</lastWaitTime> <nextWaitTime>0</nextWaitTime> <eventDef> <workClass>Event_SpawnMonster</workClass> <parameter>{"MonsterType": "Goblin", "Count": 3}</parameter> </eventDef> </li> <!-- ...更多故事阶段 --> </storyStage>
eventDef 字段 (事件定义)
- 说明:指定当前故事阶段完成后触发的事件。它可以是已经预定义好的 事件定义 的
defName引用,也可以是在此处直接定义的匿名事件。 - 引用方式:
<eventDef>EventDef的defName</eventDef> - 匿名定义方式:
<eventDef> <workClass>Event_SpawnItem</workClass> <parameter>{"ItemDefName": "HealingPotion", "Count": 1}</parameter> </eventDef>
messageDef 字段 (消息定义)
- 说明:指定当前故事阶段需要显示给玩家的消息。它可以是已经预定义好的 消息定义 的
defName引用,也可以是在此处直接定义的匿名消息。 - 引用方式:
<messageDef>MessageDef的defName</messageDef> - 匿名定义方式:
<messageDef> <type>PassiveHint</type> <text>你获得了新的任务目标!</text> <color>Yellow</color> </messageDef>
XML 使用说明 - 定义实体事件处理
在游戏配置文件中,您可以使用 <EntityEventDef> 元素来定义与游戏实体生命周期和行为相关的各种事件触发器。每个 <EntityEventDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<EntityEventDef> 提供了一种强大的机制,用于在实体执行特定动作(如移动、攻击)、经历生命周期事件(如生成、死亡)或满足特定条件时,自动触发预设的游戏事件。这使得游戏的动态性和交互性大大增强,无需硬编码即可实现复杂的事件联动。
参数说明
所有参数都必须通过嵌套元素的方式进行赋值。
-
<defName>(必需,字符串)- 该实体事件定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该实体事件定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该实体事件定义的具体内容或特殊用途。
特定行为触发事件数组
以下字段都是可选的,每个字段都是一个事件数组,当实体发生对应行为时,数组中的所有事件都会被顺序触发。数组的定义方式为:<数组名><li>事件引用/匿名定义</li><li>事件引用/匿名定义</li></数组名>。数组元素可以是已定义的 EventDef 的 defName 字符串,也可以是直接在这里定义的匿名 EventDef。
<onSpawnEvents>(可选,EventDef 数组)- 当实体首次生成时触发的一系列事件。
<onMoveForwardEvents>(可选,EventDef 数组)- 当实体向前移动时触发的一系列事件。
<onMoveBackwardEvents>(可选,EventDef 数组)- 当实体向后移动时触发的一系列事件。
<onMoveLeftEvents>(可选,EventDef 数组)- 当实体向左移动时触发的一系列事件。
<onMoveRightEvents>(可选,EventDef 数组)- 当实体向右移动时触发的一系列事件。
<onMeleeAttackEvents>(可选,EventDef 数组)- 当实体执行近战攻击时触发的一系列事件。
<onRangedAttackEvents>(可选,EventDef 数组)- 当实体执行远程攻击时触发的一系列事件。
<onHitEvents>(可选,EventDef 数组)- 当实体受到攻击或伤害时触发的一系列事件。
<onDeathEvents>(可选,EventDef 数组)- 当实体生命值归零并死亡时触发的一系列事件。
条件触发事件
<conditionalEvents>(可选,ConditionalEvent 数组)- 这是一个特殊的事件数组,其中的每个元素都是一个
<ConditionalEvent>。这些事件会在满足特定条件时才被触发。数组的定义方式与普通事件数组相同。 - 关于
<conditionalEvents>的详细讲解,请参阅条件事件详解。
- 这是一个特殊的事件数组,其中的每个元素都是一个
引用方式和匿名定义
EventDef引用/匿名定义: 在所有事件数组字段中,数组的每个<li>元素都可以是以下两种形式之一:ConditionalEvent匿名定义: 在<conditionalEvents>数组中,每个<li>元素必须是一个匿名的<ConditionalEvent>定义。
示例
带有多种实体事件的定义
<Define>
<!-- 预定义的事件,可被引用 -->
<EventDef>
<defName>Event_PlayDeathSound</defName>
<workClass>Event_PlaySound</workClass>
<parameter>{"SoundID":"DeathCry"}</parameter>
</EventDef>
<EventDef>
<defName>Event_DropLoot</defName>
<workClass>Event_ItemDrop</workClass>
<parameter>{"LootTable":"MonsterLootTable_Basic"}</parameter>
</EventDef>
<!-- 实体事件定义示例 -->
<EntityEventDef>
<defName>MonsterA_Events</defName>
<label>A型怪物事件集</label>
<description>定义A型怪物在不同行为下的事件触发。</description>
<!-- 实体生成时触发事件 -->
<onSpawnEvents>
<li>
<workClass>Event_EntityGenerater</workClass>
<parameter>
{
"DefinitionsToChooseFrom":[ { "DefName":"Effect_SpawnSmoke", "DefTypeName":"EffectDef" } ],
"LocationType":"AtEntity",
"Count":1
}
</parameter>
</li>
<li>Event_MonsterSpawnAnnounce</li> <!-- 引用另一个 EventDef -->
</onSpawnEvents>
<!-- 实体死亡时触发事件 -->
<onDeathEvents>
<li>Event_PlayDeathSound</li> <!-- 引用已定义的事件 -->
<li>Event_DropLoot</li> <!-- 引用已定义的事件 -->
<li>
<workClass>Event_CustomAnimation</workClass>
<parameter>{"AnimationStyle":"DeathExplosion"}</parameter>
</li>
</onDeathEvents>
<!-- 实体受击时触发一个匿名事件 -->
<onHitEvents>
<li>
<workClass>Event_ScreenShake</workClass>
<parameter>{"Intensity":0.5, "Duration":0.1}</parameter>
</li>
</onHitEvents>
<!-- 条件事件示例 -->
<conditionalEvents>
<li>
<parameter>HasLowHealth()</parameter>
<eventDefs>
<li>Event_MonsterFlee</li>
<li>
<workClass>Event_ApplyBuff</workClass>
<parameter>{"BuffDefName":"FearBuff"}</parameter>
</li>
</eventDefs>
</li>
<li>
<parameter>IsNightTime()</parameter>
<eventDefs>
<li>Event_EnhanceMonsterStrength</li>
</eventDefs>
</li>
</conditionalEvents>
</EntityEventDef>
</Define>
条件事件详解
<conditionalEvents> 字段是一个特殊的数组,它包含零个或多个 <ConditionalEvent> 定义。每个 <ConditionalEvent> 允许您定义一个条件,当该条件为真时,就会触发一系列与之关联的事件。
参数说明(ConditionalEvent)
每个 <ConditionalEvent> 都必须是一个匿名定义,包含以下参数:
-
<parameter>(必需,字符串)- 这是一个字符串,其内容是一个条件表达式。这个表达式的语法和可用的函数与行为树中的条件判断非常相似。它将由游戏引擎进行求值,如果结果为真,则触发
eventDefs中的事件。 - 关于可用的条件表达式和语法,请参阅行为树章节。
- 这是一个字符串,其内容是一个条件表达式。这个表达式的语法和可用的函数与行为树中的条件判断非常相似。它将由游戏引擎进行求值,如果结果为真,则触发
-
<eventDefs>(必需,EventDef 数组)- 这是一个事件数组,其中包含当
<parameter>中定义的条件为真时需要触发的所有事件。其定义方式与上面描述的事件数组完全相同,可以引用已定义的 EventDef,也可以直接匿名定义。
- 这是一个事件数组,其中包含当
示例 (conditionalEvents)
<conditionalEvents>
<li>
<!-- 条件:拥有低生命值 -->
<parameter>HasLowHealth()</parameter>
<eventDefs>
<li>Event_MonsterFlee</li> <!-- 引用一个逃跑事件 -->
<li>
<workClass>Event_ApplyBuff</workClass>
<parameter>{"BuffDefName":"FearBuff"}</parameter>
</li>
</eventDefs>
</li>
<li>
<!-- 条件:是夜晚 -->
<parameter>IsNightTime()</parameter>
<eventDefs>
<li>Event_EnhanceMonsterStrength</li> <!-- 引用一个增强力量的事件 -->
</eventDefs>
</li>
</conditionalEvents>
好的,我将根据你提供的 CharacterDef 更新文档,并新增 defaultWeapon 字段的说明。
角色定义 (CharacterDef)
CharacterDef 用于定义游戏中的各类角色实体,例如玩家、NPC、敌人等。它继承了基础的实体定义,并额外提供了内部维度(体内场景)和默认武器的配置。
根元素: <Define>
DefName: 必需,全局唯一的字符串,用于标识特定的角色定义。
Label: 可选,字符串,用于在游戏中显示的角色名称。
Description: 可选,字符串,对角色的详细描述。
参数说明
<attributes>
角色的基础属性集合。这是一个匿名定义,直接在 attributes 元素下定义各项属性。
字段说明:
<health>: 整数,角色的生命值,默认为10。<moveSpeed>: 浮点数,角色的移动速度,默认为1。<attack>: 整数,角色的攻击力,默认为1。<defense>: 整数,角色的防御力,默认为0。<attackSpeed>: 浮点数,角色的攻击速度(每次攻击的冷却时间),默认为2。<attackRange>: 浮点数,角色的攻击范围,默认为3。<attackTargetCount>: 整数,角色每次攻击能命中的目标数量,默认为1。
示例:
<attributes>
<health>100</health>
<moveSpeed>2.5</moveSpeed>
<attack>15</attack>
</attributes>
<drawingOrder>
定义角色在不同状态下(例如:闲置、行走、近战攻击、远程攻击、死亡)和不同朝向时的绘制方式。这是一个匿名定义,直接在 drawingOrder 元素下定义各种绘制节点。每个状态-朝向组合(如 idle_down、walk_up)都是一个 DrawNodeDef 类型。
字段说明:
<idle_down>,<idle_up>,<idle_left>,<idle_right>: 闲置状态下,角色朝向下方、上方、左方、右方时的绘制节点。<walk_down>,<walk_up>,<walk_left>,<walk_right>: 行走状态下,角色朝向下方、上方、左方、右方时的绘制节点。<meleeAttack_down>,<meleeAttack_up>,<meleeAttack_left>,<meleeAttack_right>: 近战攻击状态下,角色朝向下方、上方、左方、右方时的绘制节点。<rangedAttack_down>,<rangedAttack_up>,<rangedAttack_left>,<rangedAttack_right>: 远程攻击状态下,角色朝向下方、上方、左方、右方时的绘制节点。<death_down>,<death_up>,<death_left>,<death_right>: 死亡状态下,角色朝向下方、上方、左方、右方时的绘制节点。
示例:
<drawingOrder>
<idle_down>
<textures>
<li>Character_Maid_Walk_1</li>
</textures>
</idle_down>
<walk_down>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_0</li>
<li>Character_Maid_Walk_1</li>
<li>Character_Maid_Walk_2</li>
<li>Character_Maid_Walk_1</li>
</textures>
</walk_down>
<!-- 其他状态和朝向的绘制定义 -->
</drawingOrder>
<behaviorTree>
定义角色的行为逻辑树。这是一个匿名定义,直接在 behaviorTree 元素下定义行为树的根节点。其结构与 BehaviorTreeDef 一致。
示例:
<behaviorTree>
<className>ThinkNode_Selector</className>
<childTree>
<li>
<className>ThinkNode_Conditional</className>
<value>HasWeapon()</value>
<childTree>
<li>
<className>JobGiver_AttackJob</className>
</li>
</childTree>
</li>
<li>
<className>ThinkNode_Sequence</className>
<childTree>
<li><className>JobGiver_Wander</className></li>
<li><className>JobGiver_Idle</className></li>
</childTree>
</li>
</childTree>
</behaviorTree>
<affiliation>
指定角色的所属阵营。可以引用一个现有的 AffiliationDef 的 defName,或者直接在此处进行匿名定义。
作为引用:
<affiliation>player</affiliation> <!-- 引用名为 "player" 的 AffiliationDef -->
作为匿名定义:
<affiliation>
<defaultRelation>Friendly</defaultRelation>
<hostileFactions>
<li>monster</li>
</hostileFactions>
</affiliation>
<defaultWeapon>
定义角色在背包没有选择任何武器时,默认使用的武器。可以引用一个现有的 WeaponDef 的 defName,或者直接在此处进行匿名定义。
作为引用:
<defaultWeapon>BasicSword</defaultWeapon> <!-- 引用名为 "BasicSword" 的 WeaponDef -->
作为匿名定义:
<defaultWeapon>
<label>默认拳头</label>
<attack>1</attack>
<attackRange>0.8</attackRange>
<!-- 其他 WeaponDef 属性,具体字段取决于 WeaponDef 的定义 -->
</defaultWeapon>
<eventDef>
定义角色在特定事件发生时触发的行为。这是一个 EntityEventDef 类型的匿名定义。
示例:
<eventDef>
<onDeathEvents>
<li>
<workClass>CreateEffect</workClass>
<parameter>ExplosionEffect</parameter>
</li>
<li>
<workClass>DropItems</workClass>
<parameter>Gold,5-10</parameter>
</li>
</onDeathEvents>
</eventDef>
<colliderSize>
字符串,定义角色的碰撞体大小,通常为 "宽,高" 格式。例如 "1.0,1.0"。
<colliderPosition>
字符串,定义角色的碰撞体相对角色中心的位置偏移,通常为 "x,y" 格式。例如 "0.0,0.5"。
<insideDimensionDef>
引用一个 DimensionDef 的 defName,指定当角色进行“体内场景”战斗时所使用的维度定义。
示例:
<insideDimensionDef>CellularDimension</insideDimensionDef> <!-- 引用名为 "CellularDimension" 的 DimensionDef -->
示例
<Define>
<defName>maid</defName>
<label>女仆</label>
<description>一个可爱的女仆角色</description>
<!-- 角色基础属性的匿名定义 -->
<attributes>
<health>100</health>
<moveSpeed>2</moveSpeed>
<attack>10</attack>
<defense>5</defense>
<attackRange>1.5</attackRange>
</attributes>
<!-- 角色所属阵营,引用现有定义 -->
<affiliation>player</affiliation>
<!-- 角色默认武器,引用现有定义 -->
<defaultWeapon>MaidDuster</defaultWeapon>
<!-- 角色不同状态和朝向的绘制指令的匿名定义 -->
<drawingOrder>
<!-- 闲置状态 -->
<idle_up>
<textures>
<li>Character_Maid_Walk_37</li>
</textures>
</idle_up>
<idle_down>
<textures>
<li>Character_Maid_Walk_1</li>
</textures>
</idle_down>
<idle_left>
<textures>
<li>Character_Maid_Walk_13</li>
</textures>
</idle_left>
<idle_right>
<textures>
<li>Character_Maid_Walk_25</li>
</textures>
</idle_right>
<!-- 行走状态 -->
<walk_up>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_36</li>
<li>Character_Maid_Walk_37</li>
<li>Character_Maid_Walk_38</li>
<li>Character_Maid_Walk_37</li>
</textures>
</walk_up>
<walk_down>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_0</li>
<li>Character_Maid_Walk_1</li>
<li>Character_Maid_Walk_2</li>
<li>Character_Maid_Walk_1</li>
</textures>
</walk_down>
<walk_left>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_12</li>
<li>Character_Maid_Walk_13</li>
<li>Character_Maid_Walk_14</li>
<li>Character_Maid_Walk_13</li>
</textures>
</walk_left>
<walk_right>
<FPS>5.0</FPS>
<textures>
<li>Character_Maid_Walk_24</li>
<li>Character_Maid_Walk_25</li>
<li>Character_Maid_Walk_26</li>
<li>Character_Maid_Walk_25</li>
</textures>
</walk_right>
<!-- 近战攻击状态 -->
<meleeAttack_down>
<textures>
<li>testPawn_6</li>
</textures>
</meleeAttack_down>
<!-- 忽略其他攻击状态以作演示 -->
</drawingOrder>
<!-- 角色行为树的匿名定义 -->
<behaviorTree>
<className>ThinkNode_Selector</className>
<childTree>
<!-- 尝试攻击 -->
<li>
<className>ThinkNode_Sequence</className>
<childTree>
<li><className>JobNode_MoveToAttackRange</className></li>
<li><className>JobNode_AttackTarget</className></li>
</childTree>
</li>
<!-- 否则,漫无目的地游荡和闲置 -->
<li>
<className>ThinkNode_Sequence</className>
<childTree>
<li><className>JobNode_Wander</className></li>
<li><className>JobNode_Idle</className></li>
</childTree>
</li>
</childTree>
</behaviorTree>
<!-- 角色碰撞体信息 -->
<colliderSize>1.0,1.5</colliderSize>
<colliderPosition>0.0,0.75</colliderPosition>
<!-- 角色体内场景定义 -->
<insideDimensionDef>PlayerBodyDimension</insideDimensionDef>
</Define>
MonsterDef (怪物定义)
MonsterDef 用于定义游戏中的怪物实体。它继承了基础的实体定义 EntityDef,并在此基础上增加了怪物特有的武器配置。
根元素: <Define>
DefName: 必需,全局唯一的字符串,用于标识特定的怪物定义。
Label: 可选,字符串,用于在游戏中显示的怪物名称。
Description: 可选,字符串,对怪物的详细描述。
参数说明
MonsterDef 继承了 EntityDef 的所有参数:
<attributes>: 怪物的基础属性,这是一个 AttributesDef 类型的匿名定义。<drawingOrder>: 怪物的绘制指令,这是一个 DrawingOrderDef 类型的匿名定义。<behaviorTree>: 怪物的行为逻辑树,这是一个 BehaviorTreeDef 类型的匿名定义。<affiliation>: 怪物的所属阵营,可以引用一个现有的 AffiliationDef 的defName,或在此处进行匿名定义。<eventDef>: 怪物特定事件触发的行为,这是一个 EntityEventDef 类型的匿名定义。<colliderSize>: 字符串,定义角色的碰撞体大小,通常为 "宽,高" 格式。例如 "1.0,1.0"。<colliderPosition>: 字符串,定义角色的碰撞体相对角色中心的位置偏移,通常为 "x,y" 格式。例如 "0.0,0.5"。<insideDimensionDef>: 引用一个 DimensionDef 的defName,指定当怪物进行“体内场景”战斗时所使用的维度定义。
除了继承的参数外,MonsterDef 还有一个特有的参数:
<weapon>
定义怪物默认持有的武器。这是一个 WeaponDef 类型的匿名定义。
WeaponDef 包含的字段说明:
<type>: 字符串,武器的类型。"Melee" (近战武器) 或 "Ranged" (远程武器)。默认为 "Melee"。<attributes>: 武器提供的额外属性加成或改变。这是一个 AttributesDef 类型的匿名定义,与怪物自身的attributes结构相同,用于修正武器相关的属性,例如武器的攻击力、攻击速度和攻击范围。 示例:<attributes> <attack>5</attack> <attackSpeed>1.5</attackSpeed> <attackRange>2</attackRange> </attributes><bullet>: 如果武器类型为“Ranged”,则需要定义发射的子弹。可以引用一个现有的 BulletDef 的defName,或者直接在此处进行匿名定义。 作为引用:
作为匿名定义:<bullet>ArrowBullet</bullet> <!-- 引用名为 "ArrowBullet" 的 BulletDef --><bullet> <defName>FireballWeaponBullet</defName> <!-- 匿名定义也需要defName --> <image>Bullet_Fireball</image> <speed>10</speed> <damage>15</damage> </bullet><attackAnimation>: 字符串数组,指定武器的攻击动画帧。每个<li>元素内是一个贴图的defName。 示例:<attackAnimation> <li>Weapon_Sword_Swing_1</li> <li>Weapon_Sword_Swing_2</li> </attackAnimation><attackDetectionTime>: 浮点数,攻击判定发生的时间点,相对攻击动画开始的秒数。默认为0。<useEntityAttackAnimation>: 布尔值,如果为true,则优先使用怪物自身的攻击动画,武器的attackAnimation将被忽略。默认为true。
示例
<MonsterDef>
<defName>chicken</defName>
<label>不大聪明</label>
<description>一只弱小的鸡,但可能很狡猾。</description>
<attributes>
<health>20</health>
<moveSpeed>1.5</moveSpeed>
<attack>5</attack>
<defense>0</defense>
</attributes>
<drawingOrder>
<!-- 鸡的各种状态绘制,此处省略具体细节 -->
<idle_down>
<textures><li>Chicken_Idle_0</li></textures>
</idle_down>
<walk_down>
<FPS>8.0</FPS>
<textures>
<li>Chicken_Walk_0</li>
<li>Chicken_Walk_1</li>
<li>Chicken_Walk_2</li>
</textures>
</walk_down>
<meleeAttack_down>
<textures><li>Chicken_Attack_0</li><li>Chicken_Attack_1</li></textures>
<FPS>10.0</FPS>
</meleeAttack_down>
</drawingOrder>
<behaviorTree>
<className>ThinkNode_Selector</className>
<childTree>
<!-- 发现敌人则攻击 -->
<li>
<className>ThinkNode_Conditional</className>
<value>HasTarget()</value>
<childTree>
<li><className>JobGiver_AttackJob</className></li>
</childTree>
</li>
<!-- 否则随机漫游 -->
<li>
<className>ThinkNode_Sequence</className>
<childTree>
<li><className>JobGiver_Wander</className></li>
<li><className>JobGiver_Idle</className></li>
</childTree>
</li>
</childTree>
</behaviorTree>
<affiliation>monster</affiliation>
<colliderSize>0.8,0.8</colliderSize>
<colliderPosition>0.0,0.4</colliderPosition>
<!-- 怪物默认持有的武器的匿名定义 -->
<weapon>
<type>Melee</type>
<attributes>
<attack>2</attack> <!-- 武器提供2点额外攻击力 -->
<attackRange>0.8</attackRange> <!-- 武器的攻击范围 -->
<attackSpeed>1.0</attackSpeed>
</attributes>
<!-- 鸡的攻击使用自身的动画,不单独定义武器动画 -->
<useEntityAttackAnimation>true</useEntityAttackAnimation>
<attackDetectionTime>0.2</attackDetectionTime> <!-- 攻击动画播放0.2秒后进行判定 -->
</weapon>
</MonsterDef>
建筑定义 (<BuildingDef>)
功能说明
建筑定义用于在游戏中创建各种静态或动态的建筑对象。它继承自 实体定义 (<EntityDef>),这意味着建筑也具备通常实体的属性、行为和外观。
BuildingDef 特别之处在于其 buildingType 字段,它决定了建筑是作为背景瓦片存在(Static),还是作为一个可互动、有碰撞、可触发事件的实体(Dynamic)。当 buildingType 为 Dynamic 时,建筑可以拥有一个激活按键 (activateKey) 和检测范围 (detectionRadius),允许玩家在靠近时触发预定义的事件。
可用参数
由于 <BuildingDef> 继承自 <EntityDef>,它包含了所有 <EntityDef> 的参数,以及自身特有的参数。
BuildingDef 自身参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该建筑定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该建筑在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该建筑的详细描述。 |
buildingType | 枚举 (字符串) | Static | 必需。建筑类型,决定其作为瓦片还是实体。详见下文**buildingType 字段**。 |
slowDown | 浮点数 | 0.0 | 可选。当实体经过此建筑时,移动速度降低的百分比(0为不减速,1为完全停止)。 |
tile | 定义 | 无 | 可选。当 buildingType 为 Static 时使用,定义建筑作为什么 瓦片定义。详见下文**tile 字段**。 |
activateKey | 字符串 (KeyCode) | F | 可选。当 buildingType 为 Dynamic 时,玩家在触发器范围内用于激活事件的按键。 |
detectionRadius | 浮点数 | 3.0 | 可选。当 buildingType 为 Dynamic 时,玩家可激活此建筑的触发器范围。 |
triggerPosition | 字符串 | (空) | 可选。当 buildingType 为 Dynamic 时,触发器中心的相对坐标(例如:"0,0")。 |
triggerEvents | 事件定义数组 | 无 | 可选。当 buildingType 为 Dynamic 且被 activateKey 触发时,将要执行的 事件定义 数组。详见下文**triggerEvents 字段**。 |
继承自 EntityDef 的参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
attributes | 定义 | (匿名定义默认值) | 定义实体的战斗属性(如生命值、移动速度等)。可以是引用或匿名定义。 |
drawingOrder | 定义 | (空) | 定义实体在不同状态和方向下的纹理绘制顺序。这是一个匿名嵌套定义。 |
behaviorTree | 定义 | (空) | 可选。定义实体的 行为树,控制其AI行为。可以是引用或匿名定义。 |
affiliation | 定义 | (空) | 可选。定义实体的 阵营,影响其与世界其他实体的交互。可以是引用或匿名定义。 |
eventDef | 定义 | (空) | 可选。定义实体特有的 事件。可以是引用或匿名定义。 |
colliderSize | 字符串 | (空) | 可选。定义实体的碰撞体大小(例如:"1,1"表示一个1x1的方形碰撞体)。 |
colliderPosition | 字符串 | (空) | 可选。定义实体的碰撞体相对于实体的中心偏移(例如:"0,0")。 |
示例
静态建筑示例 (装饰墙)
<Define>
<!-- 瓦片定义,用于静态建筑 -->
<TileDef>
<defName>DecorativeWallTile</defName>
<label>装饰墙</label>
<texture>Resources/Terrain/Wall_Decorative.png</texture>
<movementCost>1</movementCost>
</TileDef>
<!-- 静态建筑定义,直接作为瓦片存在 -->
<BuildingDef>
<defName>DecorativeWall</defName>
<label>装饰墙</label>
<description>一堵漂亮的装饰性墙壁,没有任何互动功能。</description>
<buildingType>Static</buildingType>
<tile>DecorativeWallTile</tile> <!-- 引用上面定义的瓦片 -->
<slowDown>0.5</slowDown> <!-- 经过时减速 -->
</BuildingDef>
</Define>
动态建筑示例 (可互动终端)
<Define>
<!-- 图像定义 -->
<ImageDef>
<defName>TerminalTexture</defName>
<path>Resources/Buildings/Terminal.png</path>
</ImageDef>
<!-- 事件定义 -->
<EventDef>
<defName>OpenShopEvent</defName>
<workClass>Event_OpenUI</workClass>
<parameter>{"UIName":"ShopPanel"}</parameter>
</EventDef>
<!-- 动态建筑定义,可互动 -->
<BuildingDef>
<defName>InteractiveTerminal</defName>
<label>数据终端</label>
<description>一个可以访问商店功能的数据终端。</description>
<buildingType>Dynamic</buildingType>
<!-- 继承自EntityDef的属性 -->
<attributes>
<health>100</health>
<defense>5</defense>
<!-- 动态建筑默认没有移动速度 -->
</attributes>
<drawingOrder>
<idle_down>
<textures>
<li>TerminalTexture</li>
</textures>
</idle_down>
</drawingOrder>
<!-- 碰撞体 -->
<colliderSize>1,1</colliderSize>
<colliderPosition>0.5,0.5</colliderPosition>
<!-- BuildingDef 自身的互动属性 -->
<activateKey>E</activateKey>
<detectionRadius>1.5</detectionRadius>
<triggerPosition>0,0</triggerPosition>
<triggerEvents>
<li>OpenShopEvent</li> <!-- 引用上方定义的事件 -->
</triggerEvents>
</BuildingDef>
</Define>
复杂参数说明
buildingType 字段 (建筑类型)
- 说明:这是一个枚举值,决定了建筑在游戏中的表现形式:
Static: 静态建筑。这类建筑被视为地图的背景瓦片,不具备独立的实体属性(如生命值、碰撞体),不会移动,也不受伤害。它们主要用于填充地图,定义可通行区域或视觉效果。当buildingType为Static时,tile字段是必需的,它定义了这个静态建筑所代表的实际 瓦片定义。Dynamic: 动态建筑。这类建筑被视为一个独立的游戏实体,拥有自己的属性 (attributes)、外观 (drawingOrder)、碰撞体 (colliderSize,colliderPosition),可以被破坏,也可以进行互动。当buildingType为Dynamic时,activateKey、detectionRadius、triggerPosition和triggerEvents等字段可用于定义其互动逻辑。
- 示例:
<buildingType>Static</buildingType> <buildingType>Dynamic</buildingType>
tile 字段 (瓦片定义)
- 说明:当
buildingType设置为Static时,此字段必需。它指定了该静态建筑所使用的底层 瓦片定义。可以是预定义瓦片的defName引用,也可以是当前位置的匿名定义。 - 引用方式:
<tile>TileDef的defName</tile> - 匿名定义方式:
<tile> <label>草地</label> <texture>Resources/Terrain/Grass.png</texture> <movementCost>1</movementCost> <isWalkable>true</isWalkable> </tile>
triggerEvents 字段 (触发事件数组)
- 说明:这是一个数组,当
buildingTypeg 为Dynamic且玩家在建筑的detectionRadius范围内按下activateKey时,数组中的所有 事件定义 将按顺序被触发。每个<li>元素可以引用一个已定义的事件defName或进行匿名定义。 - 数组定义方式:
<triggerEvents> <li>EventDef的defName1</li> <li>EventDef的defName2</li> <li> <!-- 匿名定义一个事件 --> <workClass>Event_PlaySound</workClass> <parameter>{"SoundId":"ActivateBuildingSound"}</parameter> </li> </triggerEvents>
规则瓦片定义 (<TileDef>)
功能说明
规则瓦片定义用于创建一种智能瓦片,它能根据周围相邻瓦片的类型自动改变其自身的纹理、动画、碰撞体和属性。这种机制极大地简化了地图的绘制工作,尤其适用于那些需要平滑过渡或形成复杂图案的自然地形(如水体、草地边缘、道路等)。每个规则瓦片都包含一系列规则 (rules),系统会根据这些规则来决定在特定邻居条件下应该显示哪种外观。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该规则瓦片定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该瓦片在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该瓦片的详细描述。 |
collider | 枚举 (字符串) | None | 必需。瓦片的默认碰撞体类型。详见下文**collider 字段**。 |
texture | 字符串 | (空) | 可选。瓦片的默认纹理路径或名称,当没有规则匹配时使用。 |
tileCost | 浮点数 | 0.0 | 可选。当实体进入该瓦片时,其移动速度降低的百分比(0为不减速,1为完全停止)。 |
rules | 规则瓦片规则定义数组 | 无 | 必需。定义瓦片如何根据邻居生成不同外观。详见下文**rules 字段**。 |
示例
这是一个定义了水体规则瓦片的例子,它根据周围水瓦片或非水瓦片的存在来选择不同的纹理:
<Define>
<TileDef>
<defName>Water</defName>
<label>水面</label>
<description>地图上的水体瓦片,构成河流和湖泊的背景。</description>
<collider>Grid</collider> <!-- 水面具有网格碰撞体 -->
<texture>tileMap_37</texture> <!-- 默认纹理或中心水纹理 -->
<tileCost>0.5</tileCost> <!-- 经过水面时,移动速度减慢50% -->
<rules>
<!-- 规则1:周围八个方向都是水瓦片时,显示完整的中心水面 -->
<rule>
<neighborConditions>
<li>This</li><li>This</li><li>This</li>
<li>This</li> <li>This</li>
<li>This</li><li>This</li><li>This</li>
</neighborConditions>
<animationTextures>
<li>tileMap_37</li>
</animationTextures>
<outputCollider>Grid</outputCollider>
</rule>
<!-- 规则2:顶部无水瓦片,形成水体顶部边缘 -->
<rule>
<neighborConditions>
<li>Any</li><li>NotThis</li><li>Any</li>
<li>This</li> <li>This</li>
<li>This</li><li>This</li><li>This</li>
</neighborConditions>
<animationTextures>
<li>tileMap_19</li>
</animationTextures>
<outputCollider>Grid</outputCollider>
</rule>
<!-- 规则3:左侧无水瓦片,形成水体左侧边缘 -->
<rule>
<neighborConditions>
<li>Any</li><li>This</li><li>This</li>
<li>NotThis</li> <li>This</li>
<li>Any</li><li>This</li><li>This</li>
</neighborConditions>
<animationTextures>
<li>tileMap_36</li>
</animationTextures>
<outputCollider>Grid</outputCollider>
</rule>
<!-- ... 更多规则,定义了水体不同边缘和角的纹理 -->
<!-- 规则10:左上无水瓦片,顶中和左中是水瓦片,形成左上角内凹 -->
<rule>
<neighborConditions>
<li>NotThis</li><li>This</li><li>Any</li>
<li>This</li> <li>This</li>
<li>Any</li><li>This</li><li>This</li>
</neighborConditions>
<animationTextures>
<li>tileMap_90</li>
</animationTextures>
<outputCollider>Grid</outputCollider>
</rule>
<!-- 规则20:完全独立的水单元,孤立于所有其他瓦片 -->
<rule>
<neighborConditions>
<li>Any</li><li>NotThis</li><li>Any</li>
<li>NotThis</li> <li>NotThis</li>
<li>Any</li><li>NotThis</li><li>Any</li>
</neighborConditions>
<animationTextures>
<li>tileMap_73</li> <!-- 示例:孤立水图标 -->
</animationTextures>
<outputCollider>Grid</outputCollider>
</rule>
</rules>
</TileDef>
</Define>
规则瓦片规则定义 (<RuleTileRuleDef>)
功能说明
每个规则瓦片规则定义(通常作为 规则瓦片定义 (<TileDef>) 内部的匿名定义存在)规定了在满足特定邻居条件时,该瓦片应该采用何种外观、动画、碰撞体和变换方式。规则按顺序评估,第一个匹配的规则将被应用。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 可选。该规则的唯一标识符(作为匿名定义时可省略)。 |
label | 字符串 | (空) | 可选。该规则的描述性标签。 |
description | 字符串 | (空) | 可选。该规则的详细描述。 |
neighborConditions | 邻居条件枚举数组 | [Any,Any,...,Any] | 必需。定义周围八个方向(中心瓦片周围的3x3网格,去除自身)的瓦片条件。详见下文**neighborConditions 字段**。 |
neighborConditionExtend | 邻居条件定义数组 | 无 | 可选。用于定义更复杂或非标准位置的邻居条件。详见下文**neighborConditionExtend 字段**。 |
outputType | 枚举 (字符串) | Single | 可选。瓦片的输出类型,例如单个精灵、固定动画或随机精灵。 |
transform | 枚举 (字符串) | Fixed | 可选。输出精灵的变换方式,例如固定方向或随机旋转。 |
outputCollider | 枚举 (字符串) | None | 可选。此规则生效时,瓦片采用的碰撞体类型。会覆盖 TileDef 中的 collider 值。 |
chance | 浮点数 | 0.5 | 可选。当多个规则匹配时,此规则被选中的相对概率。 |
animationTextures | 字符串列表 | 无 | 可选。当 outputType 为 Animation 时,定义动画帧的纹理路径或名称列表。 |
animationSpeed | 浮点数 | 1.0 | 可选。动画播放速度。 |
tileCost | 浮点数 | 0.0 | 可选。此规则生效时,瓦片的移动成本(减速率0-1)。会覆盖 TileDef 中的 tileCost 值。 |
复杂参数说明
collider 字段 (瓦片碰撞体类型)
- 说明:定义瓦片的碰撞体类型。
- 可选值:
None: 无碰撞体,实体可以自由穿过。Grid: 网格碰撞体,通常用于阻挡实体移动。Sprite: 使用瓦片纹理的像素数据生成碰撞体,提供更精确的碰撞区域。
- 示例:
<collider>Grid</collider>
rules 字段 (规则瓦片规则定义数组)
- 说明:这是一个数组,每个
<li>元素包含一个 规则瓦片规则定义。这些规则会按顺序进行评估,直到找到第一个满足条件的规则并应用其输出。 - 数组定义方式:
<rules> <rule> <!-- 规则1的匿名定义 --> <neighborConditions> <li>Any</li><li>NotThis</li><li>Any</li> <li>This</li> <li>This</li> <li>This</li><li>This</li><li>This</li> </neighborConditions> <animationTextures> <li>tileMap_19</li> </animationTextures> </rule> <rule> <!-- 规则2的匿名定义 --> <neighborConditions> <li>Any</li><li>This</li><li>This</li> <li>NotThis</li> <li>This</li> <li>Any</li><li>This</li><li>This</li> </neighborConditions> <animationTextures> <li>tileMap_36</li> </animationTextures> </rule> <!-- ... 更多规则 --> </rules>
neighborConditions 字段 (邻居条件数组)
- 说明:这是一个固定大小为8的数组,按顺时针方向定义了中心瓦片周围八个邻居的条件,从左上角开始。
瓦片位置(数字代表数组索引):
[0] [1] [2][7] [.] [3](.是当前瓦片自身)[6] [5] [4] - 相邻条件类型 (
NeighborConditionType):Any: 任何类型的瓦片都可以。This: 邻居瓦片必须与当前规则瓦片定义的是同类型瓦片。NotThis: 邻居瓦片不能是当前规则瓦片定义的是同类型瓦片。
- 数组定义方式:
这个例子表示要求所有八个邻居都是当前瓦片类型。<neighborConditions> <li>This</li><li>This</li><li>This</li> <!-- 左上、上、右上 --> <li>This</li> <li>This</li> <!-- 左、右 --> <li>This</li><li>This</li><li>This</li> <!-- 左下、下、右下 --> </neighborConditions>
neighborConditionExtend 字段 (扩展邻居条件数组)
- 说明:这是一个数组,允许定义除了标准8个邻居之外,任意偏移位置的邻居条件。每个
<li>元素包含一个 邻居条件定义 (<NeighborConditionDef>) 的匿名定义或引用。 - 数组定义方式:
<neighborConditionExtend> <li> <position>2,0</position> <!-- 距离中心瓦片右侧2格的瓦片 --> <Type>NotThis</Type> </li> <li> <!-- 引用已定义的扩展邻居条件 --> <defName>FarNeighborIsGrass</defName> </li> </neighborConditionExtend>
outputCollider 字段 (输出碰撞体) 与 tileCost 字段 (瓦片移动成本)
- 说明:这些字段允许你在特定规则生效时,动态地改变瓦片的碰撞体类型和移动成本(减速率)。如果规则中定义了这些值,它们将覆盖 TileDef 中对应的默认值。
- 示例:
<outputCollider>Grid</outputCollider> <tileCost>0.8</tileCost> <!-- 当此规则生效时,移动减速80% -->
animationTextures 字段 (动画精灵列表)
- 说明:这是一个字符串列表,指定了动画的每一帧所使用的纹理资源路径或名称。当规则的
outputType为Animation时,这些纹理会按顺序播放,形成动画效果。 - 列表定义方式:
<animationTextures> <li>tileMap_37</li> <li>tileMap_38</li> <li>tileMap_39</li> </animationTextures>
邻居条件定义 (<NeighborConditionDef>)
功能说明
邻居条件定义通常作为 规则瓦片规则定义 (<RuleTileRuleDef>) 中 neighborConditionExtend 字段的匿名定义或引用,用于指定除了标准8个方向之外的、任意偏移位置的瓦片需要满足的条件。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 可选。该邻居条件的唯一标识符(作为匿名定义时可省略)。 |
label | 字符串 | (空) | 可选。该邻居条件的描述性标签。 |
description | 字符串 | (空) | 可选。该邻居条件的详细描述。 |
position | 字符串 | 无 | 必需。相对于中心瓦片的位置偏移,格式为 "X,Y"(例如:"1,0"表示右侧一格,"-1,1"表示左上角对角线一格)。 |
Type | 枚举 (字符串) | Any | 必需。该位置上的瓦片需要满足的条件。详见上文**neighborConditions 字段中的相邻条件类型 (NeighborConditionType)**。 |
示例
这是一个定义了一个扩展邻居条件的例子:
<!-- 在 RuleTileRuleDef 中的使用 -->
<rule>
<!-- ...其他规则条件... -->
<neighborConditionExtend>
<li>
<position>2,0</position> <!-- 距离中心瓦片右侧2格的瓦片 -->
<Type>NotThis</Type> <!-- 要求右侧2格的瓦片不能是当前规则瓦片类型 -->
</li>
<li>
<position>0,-3</position> <!-- 距离中心瓦片下方3格的瓦片 -->
<Type>This</Type> <!-- 要求下方3格的瓦片必须是当前规则瓦片类型 -->
</li>
</neighborConditionExtend>
<!-- ...其他输出属性... -->
</rule>
地图生成器定义 (<MapGeneratorDef>)
功能说明
地图生成器定义用于配置负责生成游戏地图不同元素的逻辑。每个地图生成器都指定了一个具体的工作类 (workClass),该工作类会根据提供的配置值 (value) 来执行地图的某一部分生成任务,例如生成地形、放置建筑、植被等。这些生成器是模块化的,可以组合起来构建复杂的地图布局。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该地图生成器定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该生成器在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该生成器的详细描述。 |
workClass | 字符串 | 无 | 必需。指定处理地图生成逻辑的后端类名。详见下文**workClass 字段**。 |
value | JSON字符串 | 无 | 必需。包含传递给 workClass 的所有必要参数。详见下文**value 字段 (JSON 格式详解)**。 |
示例
以下展示了几种不同类型的地图生成器定义:
<Define>
<!-- 树木地图生成器 -->
<MapGeneratorDef>
<defName>TreeGenerator</defName>
<label>树木地图生成器</label>
<description>一个简单的树木地图生成器,根据密度填充地图为树木。</description>
<workClass>PlantMapGenerator</workClass>
<value>
{
"tileDefName":"Tree", <!-- 要生成的树木TileDef名称 -->
"mapCellSizeX":50, <!-- 地图的X轴大小 -->
"mapCellSizeY":50, <!-- 地图的Y轴大小 -->
"requiredBaseTileDefName":"Grass", <!-- 必须在什么基础地形上生成 -->
"density":0.2, <!-- 树木的生成密度 -->
"threshold":0, <!-- 生成阈值,用于控制perlin噪声或随机性 -->
"Scale":5 <!-- 用于perlin噪声的缩放因子 -->
}
</value>
</MapGeneratorDef>
<!-- 基地建筑生成器 - 放置特定模式的建筑 -->
<MapGeneratorDef>
<defName>BaseBuildingGenerator</defName>
<label>基地建筑生成器</label>
<description>一个简单的基地建筑生成器,根据预定义模式放置建筑。</description>
<workClass>BuildingMapGenerator</workClass>
<value>
{
"defName":"ConcreteWall", <!-- 默认填充的实体DefName -->
"positionX":9, <!-- 建筑模式的起始X坐标 -->
"positionY":20, <!-- 建筑模式的起始Y坐标 -->
"mapping": <!-- 数字与DefName的映射关系 -->
{
"1":"ConcreteWall",
"2":"SkillTreeShop",
"3":"StartPoint"
},
"pattern": [ <!-- 建筑布局模式,0代表不放置,1-9代表按mapping放置 -->
[2,0,0,0,0,0,0,0,0,0,0,0,0,3],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1]
]
}
</value>
</MapGeneratorDef>
<!-- 基地地板填充生成器 -->
<MapGeneratorDef>
<defName>BaseFloorFiller</defName>
<label>基地地板填充</label>
<description>一个简单的基地地板填充生成器,填充指定区域为基地地板。</description>
<workClass>BasicTerrainMapGenerator</workClass>
<value>
{
"tileDefName":"BaseFloor", <!-- 要填充的TileDef名称 -->
"mapCellSizeX":30, <!-- 填充区域的X轴大小 -->
"mapCellSizeY":30, <!-- 填充区域的Y轴大小 -->
"threshold":-1, <!-- 生成阈值,-1常用于完全填充 -->
"Scale":2, <!-- 缩放因子 -->
"offsetX":0, <!-- 填充区域的X轴偏移 -->
"offsetY":0 <!-- 填充区域的Y轴偏移 -->
}
</value>
</MapGeneratorDef>
<!-- 基地顶部墙面绘制生成器 -->
<MapGeneratorDef>
<defName>BaseUpWallFiller</defName>
<label>基地顶部墙面绘制</label>
<description>在地图顶部绘制一层基地墙面。</description>
<workClass>BasicTerrainMapGenerator</workClass>
<value>
{
"tileDefName":"BaseWall", <!-- 要填充的TileDef名称 -->
"mapCellSizeX":30, <!-- 墙面区域的X轴大小 -->
"mapCellSizeY":1, <!-- 墙面区域的Y轴大小 -->
"threshold":-1, <!-- 生成阈值 -->
"Scale":2, <!-- 缩放因子 -->
"originX":0, <!-- 墙面起始X坐标 -->
"originY":30 <!-- 墙面起始Y坐标 -->
}
</value>
</MapGeneratorDef>
</Define>
复杂参数说明
workClass 字段 (工作类)
- 说明:指定负责实际地图生成逻辑的后端类名。此字符串必须精确匹配到游戏中对应的地图生成器类。不同的
workClass会需要不同结构的value参数。 - 示例:
<workClass>PlantMapGenerator</workClass> <workClass>BuildingMapGenerator</workClass> <workClass>BasicTerrainMapGenerator</workClass> - 注意:
workClass定义的详细讲解将在 第三章:核心工作类定义 中提供。
value 字段 (JSON 格式详解)
-
说明:这是一个 JSON 格式的字符串,包含了传递给
workClass指定的地图生成器类的所有必要参数。value的内部结构和字段名必须与workClass所期望的参数类型严格匹配。 -
JSON 格式的特点:
- 键值对:由键(字符串)和值组成,键和值之间用冒号
:分隔。 - 对象:用大括号
{}包裹,包含零个或多个键值对,键值对之间用逗号,分隔。 - 数组:用方括号
[]包裹,包含零个或多个值,值之间用逗号,分隔。 - 数据类型:支持字符串、数字、布尔值 (
true/false)、JSON 对象、JSON 数组和null。
- 键值对:由键(字符串)和值组成,键和值之间用冒号
-
编写规则:
- 整个 JSON 结构必须是合法的。
- 所有键(字段名)必须用双引号
""包裹。 - 所有字符串值也必须用双引号
""包裹。数字、布尔值不需要。 - JSON 内部可以包含换行符和缩进,以提高可读性,这些空白字符在解析时会被忽略。
-
不同
workClass对应的value结构示例:-
PlantMapGenerator的value(如TreeGenerator示例所示):{ "tileDefName":"Tree", "mapCellSizeX":50, "mapCellSizeY":50, "requiredBaseTileDefName":"Grass", "density":0.2, "threshold":0, "Scale":5 }这些参数通常用于控制植被的类型、生成范围、密度以及基于Perlin噪声的分布。
-
BuildingMapGenerator的value(如BaseBuildingGenerator示例所示):{ "defName":"ConcreteWall", "positionX":9, "positionY":20, "mapping": { "1":"ConcreteWall", "2":"SkillTreeShop", "3":"StartPoint" }, "pattern": [ [2,0,0,0,0,0,0,0,0,0,0,0,0,3], ] }这些参数通常用于定义一个二维的建筑放置模式,通过
mapping将模式中的数字映射到具体的实体定义。 -
BasicTerrainMapGenerator的value(如BaseFloorFiller示例所示):{ "tileDefName":"BaseFloor", "mapCellSizeX":30, "mapCellSizeY":30, "threshold":-1, "Scale":2, "offsetX":0, "offsetY":0 }这些参数通常用于在指定区域填充单一类型的地形或方块,通过
mapCellSizeX,mapCellSizeY,offsetX,offsetY来定义区域范围。
-
-
注意事项:
value中的 JSON 结构必须与workClass内部定义的参数类结构完全匹配,包括字段名的大小写和数据类型。任何不匹配都可能导致地图生成器无法正确执行。- 为了配置文件的可读性和易维护性,强烈建议使用多行和缩进来格式化
value的内容。
维度定义 (<DimensionDef>)
功能说明
维度定义用于配置游戏中的一个独立“维度”或“地图”,它是一个可玩的游戏区域。每个维度都会指定一套地图生成器 (mapGenerators) 来构建其地形、放置初始建筑或植被等。此外,它还可以关联一个故事情节 (story) 作为该维度的开场或主线,并包含用于游戏启动界面展示的图标 (icon) 和玩家是否可以在游戏开始时选择该维度的标志 (canSelect)。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该维度定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该维度在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该维度的详细描述。 |
mapGenerators | 地图生成器数组 | 无 | 必需。定义构建此维度的地图生成器链。详见下文**mapGenerators 字段**。 |
icon | 字符串 | (空) | 可选。用于在游戏开始界面选择地图时显示的图标路径。 |
canSelect | 布尔值 | true | 可选。指示玩家是否可以在游戏开始时直接选择该维度作为起始地图。 |
story | 定义 | 无 | 可选。关联到该维度的一个故事情节定义,常用于开场引导或主线剧情。详见下文**story 字段**。 |
示例
这是一个定义了一个可选择的、包含多个地图生成器和开场故事的维度示例:
<Define>
<!-- 引用或匿名定义的地图生成器 -->
<MapGeneratorDef defName="GrasslandsTerrain">
<workClass>BasicTerrainMapGenerator</workClass>
<value>{"tileDefName":"Grass", "mapCellSizeX":100, "mapCellSizeY":100, "threshold":-1, "Scale":1}</value>
</MapGeneratorDef>
<MapGeneratorDef defName="ForestScatter">
<workClass>PlantMapGenerator</workClass>
<value>{"tileDefName":"Tree", "mapCellSizeX":100, "mapCellSizeY":100, "requiredBaseTileDefName":"Grass", "density":0.3, "threshold":0.1, "Scale":10}</value>
</MapGeneratorDef>
<!-- 引用或匿名定义的故事 -->
<StoryDef defName="StartingSequence">
<storyStage>
<li>
<nextWaitTime>3</nextWaitTime>
<messageDef defName="WelcomeMessage"/> <!-- 引用已定义的消息 -->
</li>
<li>
<lastWaitTime>3</lastWaitTime>
<nextWaitTime>0</nextWaitTime>
<eventDef defName="SpawnPlayerBase"/> <!-- 引用已定义的事件 -->
</li>
</storyStage>
</StoryDef>
<!-- 维度定义 -->
<DimensionDef>
<defName>ForestDimension</defName>
<label>茂密森林</label>
<description>一个绿意盎然、植被茂密的维度,适合喜爱自然风光的玩家。</description>
<icon>UI/DimensionIcons/ForestMap</icon> <!-- 图标路径 -->
<canSelect>true</canSelect> <!-- 玩家可以从菜单中选择此地图 -->
<mapGenerators>
<li>GrasslandsTerrain</li> <!-- 引用已定义的地图生成器 -->
<li>ForestScatter</li>
<li>
<!-- 匿名定义的地图生成器,用于在特定位置生成起始点 -->
<workClass>BuildingMapGenerator</workClass>
<value>
{
"defName":"StartPoint",
"positionX":50,
"positionY":50,
"mapping":{"1":"StartPoint"},
"pattern":[[1]]
}
</value>
</li>
</mapGenerators>
<story>StartingSequence</story> <!-- 引用已定义的故事 -->
</DimensionDef>
<DimensionDef>
<defName>TutorialDimension</defName>
<label>新手教学</label>
<description>带领新玩家熟悉游戏基础操作的教学维度。</description>
<icon>UI/DimensionIcons/TutorialMap</icon>
<canSelect>false</canSelect> <!-- 此地图仅在特定条件下加载,玩家不能手动选择 -->
<mapGenerators>
<li>
<workClass>BasicTerrainMapGenerator</workClass>
<value>{"tileDefName":"TutorialGround", "mapCellSizeX":30, "mapCellSizeY":30, "threshold":-1, "Scale":1}</value>
</li>
<!-- ...更多教学地图生成器 -->
</mapGenerators>
<story>
<!-- 匿名定义一个简单的教学故事 -->
<storyStage>
<li>
<nextWaitTime>5</nextWaitTime>
<messageDef>
<type>ScreenCenterLargeText</type>
<text>欢迎来到教学!</text>
<color>Yellow</color>
</messageDef>
</li>
</storyStage>
</story>
</DimensionDef>
</Define>
复杂参数说明
mapGenerators 字段 (地图生成器数组)
- 说明:这是一个数组,包含了用于构建当前维度的所有 地图生成器定义。数组中的
<li>元素会按顺序执行。每个<li>都可以通过引用已定义的地图生成器defName或直接进行匿名定义来指定一个地图生成器。 - 数组定义方式:
<mapGenerators> <li>MapGeneratorDef的defName1</li> <li>MapGeneratorDef的defName2</li> <li> <!-- 匿名定义一个地图生成器 --> <workClass>AnotherMapGeneratorClass</workClass> <value> { "paramA": "valueA", "paramB": 123 } </value> </li> </mapGenerators>
story 字段 (故事定义)
- 说明:关联到该维度的 故事定义。这可以是一个预定义故事的
defName引用,也可以是在此处直接定义的匿名故事。通常用于在进入该维度时播放开场剧情或设置主线任务。 - 引用方式:
<story>StoryDef的defName</story> - 匿名定义方式:
<story> <storyStage> <li> <nextWaitTime>5</nextWaitTime> <messageDef> <type>ScreenCenterLargeText</type> <text>新世界,新冒险!</text> </messageDef> </li> </storyStage> </story>
技能树定义 (<SkillTreeDef>)
功能说明
技能树定义用于构建游戏中的技能树系统,它定义了技能树中的独立节点。每个技能节点可以有特定的标签 (tag)、在用户界面中的位置 (position)、解锁所需的成本 (cost),并可选地绑定到特定阵营 (faction)。更重要的是,每个技能节点可以定义一系列前置技能 (prerequisites),以及成功解锁后能带来的增益,例如解锁新的武器 (unlockedWeapons) 或获得特定的状态效果/增益/减益 (unlockedHediffs)。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该技能树节点定义的唯一标识符。 |
label | 字符串 | (空) | 可选。该技能节点在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该技能节点的详细描述。 |
tag | 字符串 | Default | 可选。用于对技能进行分类或分组的标签(例如:"Combat", "Crafting", "Exploration")。 |
position | 字符串 | (空) | 可选。该技能节点在技能树UI中的相对位置,通常为"X,Y"格式(如"100,50")。 |
cost | 整数 | 10 | 可选。解锁该技能节点所需消耗的资源点数或其他成本。 |
faction | 定义 | 无 | 可选。指定此技能节点仅对特定 阵营定义 生效。可以是引用或匿名定义。详见下文**faction 字段**。 |
prerequisites | 技能树定义数组 | 无 | 可选。解锁此技能节点前必须先解锁的所有 技能树定义 数组。可以是引用或匿名定义。详见下文**prerequisites 字段**。 |
unlockedWeapons | 武器定义数组 | 无 | 可选。解锁此技能后获得的 武器定义 数组。可以是引用或匿名定义。详见下文**unlockedWeapons 字段**。 |
unlockedHediffs | Hediff定义数组 | 无 | 可选。解锁此技能后获得的 Hediff 定义 数组(如增益状态、新能力等)。可以是引用或匿名定义。详见下文**unlockedHediffs 字段**。 |
示例
这是一个完整的技能树定义示例,展示了不同技能节点之间的依赖关系以及解锁内容:
<Define>
<!-- 阵营定义 (如果需要) -->
<AffiliationDef>
<defName>PlayerFaction</defName>
<label>玩家阵营</label>
</AffiliationDef>
<!-- 武器定义 (如果需要) -->
<WeaponDef>
<defName>BasicPistol</defName>
<label>基础手枪</label>
<!-- ...其他武器属性... -->
</WeaponDef>
<WeaponDef>
<defName>AdvancedRifle</defName>
<label>高级步枪</label>
<!-- ...其他武器属性... -->
</WeaponDef>
<!-- Hediff 定义 (如果需要) -->
<HediffDef>
<defName>IncreasedHealthBuff</defName>
<label>生命值强化</label>
<!-- ...其他Hediff属性... -->
</HediffDef>
<HediffDef>
<defName>FastReloadBuff</defName>
<label>快速换弹</label>
<!-- ...其他Hediff属性... -->
</HediffDef>
<!-- 技能树节点定义 -->
<SkillTreeDef>
<defName>BasicCombat</defName>
<label>基础战斗训练</label>
<description>提高基础战斗能力。</description>
<tag>Combat</tag>
<position>100,100</position>
<cost>5</cost>
<faction>PlayerFaction</faction> <!-- 引用阵营 -->
<unlockedWeapons>
<li>BasicPistol</li> <!-- 解锁基础手枪 -->
</unlockedWeapons>
<unlockedHediffs>
<li>
<!-- 匿名定义一个生命值强化 Hediff -->
<defName>MinorHealthBoost</defName>
<label>微量生命值提升</label>
<description>永久提升少量生命值上限。</description>
<isPermanent>true</isPermanent>
<effect>HealthMax_Add_5</effect>
</li>
</unlockedHediffs>
</SkillTreeDef>
<SkillTreeDef>
<defName>AdvancedMarksmanship</defName>
<label>高级射击技巧</label>
<description>解锁高级武器并提高射击精度。</description>
<tag>Combat</tag>
<position>250,150</position>
<cost>15</cost>
<faction>PlayerFaction</faction>
<prerequisites>
<li>BasicCombat</li> <!-- 前置技能:基础战斗训练 -->
</prerequisites>
<unlockedWeapons>
<li>AdvancedRifle</li> <!-- 解锁高级步枪 -->
</unlockedWeapons>
<unlockedHediffs>
<li>FastReloadBuff</li> <!-- 解锁快速换弹 Hediff -->
</unlockedHediffs>
</SkillTreeDef>
<SkillTreeDef>
<defName>MedicalExpertise</defName>
<label>医疗专精</label>
<description>提高医疗效率和治疗能力。</description>
<tag>Support</tag>
<position>100,300</position>
<cost>10</cost>
<faction>PlayerFaction</faction>
<unlockedHediffs>
<li>
<!-- 匿名定义一个治疗效果提升 Hediff -->
<defName>HealingEfficiency</defName>
<label>治疗效率提升</label>
<effect>HealingRate_Multiply_1.2</effect>
<description>治疗物品和能力效果提高20%。</description>
</li>
</unlockedHediffs>
</SkillTreeDef>
</Define>
复杂参数说明
faction 字段 (阵营定义)
- 说明:可选。指定此技能节点仅对特定 阵营定义 内的实体生效或可见。
- 引用方式:
<faction>AffiliationDef的defName</faction> - 匿名定义方式:
<faction> <defName>AncientRace</defName> <label>古老文明</label> <description>一个古老而神秘的阵营。</description> <!-- ...更多阵营属性... --> </faction>
prerequisites 字段 (技能树定义数组)
- 说明:这是一个数组,包含了解锁当前技能节点所需要预先解锁的所有 技能树定义。数组中的每个
<li>元素可以引用一个已定义的技能树defName或直接进行匿名定义。 - 数组定义方式:
<prerequisites> <li>RequiredSkillOne</li> <!-- 引用前置技能 --> <li>RequiredSkillTwo</li> <li> <!-- 匿名定义一个简单前置技能 --> <defName>MinorEndurance</defName> <label>小幅耐力</label> <cost>2</cost> </li> </prerequisites>
unlockedWeapons 字段 (武器定义数组)
- 说明:这是一个数组,包含了成功解锁当前技能节点后,玩家将(或可以)获得的 武器定义。数组中的每个
<li>元素可以引用一个已定义的武器defName或直接进行匿名定义。 - 数组定义方式:
<unlockedWeapons> <li>PlasmaRifle</li> <!-- 解锁等离子步枪 --> <li> <!-- 匿名定义一个临时解锁的武器 --> <defName>TemporaryFlamethrower</defName> <label>临时火焰喷射器</label> <duration>600</duration> <!-- 可用时间 --> <!-- ...其他武器属性... --> </li> </unlockedWeapons>
unlockedHediffs 字段 (Hediff定义数组)
- 说明:这是一个数组,包含了成功解锁当前技能节点后,实体将获得的所有 Hediff 定义(状态效果、增益、减益、新能力等)。数组中的每个
<li>元素可以引用一个已定义的 HediffdefName或直接进行匿名定义。 - 数组定义方式:
<unlockedHediffs> <li>AdrenalineRush</li> <!-- 解锁肾上腺素激增状态 --> <li> <!-- 匿名定义一个移动速度提升 Hediff --> <defName>EnhancedSpeed</defName> <label>增强速度</label> <isPermanent>true</isPermanent> <effect>MoveSpeed_Multiply_1.1</effect> <description>永久提升10%移动速度。</description> </li> </unlockedHediffs>
健康定义 (<HediffDef>)
功能说明
健康定义(HediffDef)用于定义游戏中各种状态效果、增益或减益。它可以是一个临时的加速效果,一个持续的毒素伤害,一个永久的生命值上限提升,或者其他任何能在一段时间内或永久影响实体属性或行为的状态。Hediff可以具有多个发展阶段,并在不同的阶段表现出不同的效果。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 必需。该健康定义(Hediff)的唯一标识符。 |
label | 字符串 | (空) | 可选。该状态效果在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该状态效果的详细描述。 |
time | 浮点数 | -1.0 | 必需。状态效果的持续时间(秒)。设置为 -1 表示该效果是永久性的。 |
stages | Hediff阶段定义数组 | 无 | 可选。定义该Hediff在不同时间点所表现出的效果阶段。详见下文**stages 字段**。 |
comps | Hediff组件定义数组 | 无 | 可选。为该Hediff附加额外的功能组件,实现复杂行为。详见下文**comps 字段**。 |
示例
示例1:简单的临时加速效果
<Define>
<HediffDef>
<defName>TemporarySpeedBoost</defName>
<label>加速</label>
<description>暂时提升移动速度。</description>
<time>10</time> <!-- 持续10秒 -->
<stages>
<li>
<start>0</start> <!-- 从 Hediff 出现时立即生效 -->
<attributesOffset>
<moveSpeedPercentOffset>0.5</moveSpeedPercentOffset> <!-- 移动速度提升50% -->
</attributesOffset>
</li>
</stages>
</HediffDef>
</Define>
示例2:具有多个阶段的毒素效果
<Define>
<HediffDef>
<defName>ToxicExposure</defName>
<label>毒素暴露</label>
<description>受到毒素影响,随时间恶化。</description>
<time>30</time> <!-- 总持续30秒 -->
<stages>
<li>
<start>0</start> <!-- 0-10秒:轻微阶段 -->
<label>轻度中毒</label>
<attributesOffset>
<moveSpeedPercentOffset>-0.1</moveSpeedPercentOffset> <!-- 10%减速 -->
</attributesOffset>
</li>
<li>
<start>10</start> <!-- 10-20秒:中度阶段 -->
<label>中度中毒</label>
<attributesOffset>
<moveSpeedPercentOffset>-0.25</moveSpeedPercentOffset> <!-- 25%减速 -->
<healthOffset>-0.1</healthOffset> <!-- 每秒损失0.1生命值(通过Comp实现) -->
</attributesOffset>
</li>
<li>
<start>20</start> <!-- 20-30秒:重度阶段 -->
<label>重度中毒</label>
<attributesOffset>
<moveSpeedPercentOffset>-0.5</moveSpeedPercentOffset> <!-- 50%减速 -->
<attackPercentOffset>-0.2</attackPercentOffset> <!-- 攻击力降低20% -->
<healthOffset>-0.3</healthOffset> <!-- 每秒损失0.3生命值 -->
</attributesOffset>
</li>
</stages>
<comps>
<li>
<!-- 范例:一个自定义组件,负责根据attributesOffset.healthOffset属性造成持续伤害 -->
<compClass>HediffComp_DamageOverTime</compClass>
<properties>{"damageType":"Poison", "tickInterval":1.0}</properties>
</li>
</comps>
</HediffDef>
</Define>
Hediff阶段定义 (<HediffStageDef>)
功能说明
Hediff阶段定义(HediffStageDef)用于描述一个特定状态效果在不同发展阶段的具体属性偏移。一个具有多个阶段的Hediff可以在其持续时间内,随着时间的推移从一个阶段过渡到另一个阶段,从而表现出不同的效果。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 可选。该阶段的唯一标识符(作为匿名定义时可省略)。 |
label | 字符串 | (空) | 可选。该阶段在游戏中显示的名称。 |
description | 字符串 | (空) | 可选。该阶段的详细描述。 |
start | 浮点数 | 0.0 | 必需。该阶段开始的时间点。例如,如果所属Hediff的总持续时间为10秒,start 为5,则此阶段从Hediff出现5秒后开始生效。对于永久性Hediff (HediffDef.time 为 -1),阶段按其 start 值从小到大顺序匹配,直到某个 start 值大于当前Hediff已持续时间或匹配到最后一个阶段。 |
attributesOffset | 属性偏移定义 | (匿名定义默认值) | 必需。定义此阶段对实体属性造成的偏移量。可以是引用或匿名定义。详见下文**attributesOffset 字段**。 |
复杂参数说明
attributesOffset 字段 (属性偏移定义)
- 说明:这是一个 属性偏移定义 (
<AttributesOffsetDef>) 的匿名定义或引用。它详细说明了该 Hediff 阶段对实体各项属性(如生命值、移动速度、攻击力等)造成的具体影响,包括绝对值偏移和百分比偏移。 - 匿名定义方式:
<attributesOffset> <healthOffset>-5</healthOffset> <!-- 生命值上限减少5 --> <moveSpeedPercentOffset>0.2</moveSpeedPercentOffset> <!-- 移动速度提高20% --> </attributesOffset>
属性偏移定义 (<AttributesOffsetDef>)
功能说明
属性偏移定义(AttributesOffsetDef)是一个辅助定义,通常作为 Hediff阶段定义 (<HediffStageDef>) 中的匿名定义,用于详细指定对实体各项属性的修改量。这些修改可以是直接的数值增减(绝对值偏移),也可以是基于现有属性值的百分比增减(百分比偏移)。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 可选。该偏移定义的唯一标识符(作为匿名定义时可省略)。 |
label | 字符串 | (空) | 可选。该偏移的描述性标签。 |
description | 字符串 | (空) | 可选。该偏移的详细描述。 |
healthOffset | 浮点数 | 0.0 | 生命值上限的绝对值偏移量。 |
moveSpeedOffset | 浮点数 | 0.0 | 移动速度的绝对值偏移量。 |
attackOffset | 浮点数 | 0.0 | 攻击力的绝对值偏移量。 |
defenseOffset | 浮点数 | 0.0 | 防御力的绝对值偏移量。 |
attackSpeedOffset | 浮点数 | 0.0 | 攻击速度的绝对值偏移量。 |
attackRangeOffset | 浮点数 | 0.0 | 攻击范围的绝对值偏移量。 |
attackTargetCountOffset | 浮点数 | 0.0 | 攻击目标数量的绝对值偏移量。 |
healthPercentOffset | 浮点数 | 0.0 | 生命值上限的百分比偏移量(例如 0.1 表示 +10%,-0.5 表示 -50%)。 |
moveSpeedPercentOffset | 浮点数 | 0.0 | 移动速度的百分比偏移量。 |
attackPercentOffset | 浮点数 | 0.0 | 攻击力的百分比偏移量。 |
defensePercentOffset | 浮点数 | 0.0 | 防御力的百分比偏移量。 |
attackSpeedPercentOffset | 浮点数 | 0.0 | 攻击速度的百分比偏移量。 |
attackRangePercentOffset | 浮点数 | 0.0 | 攻击范围的百分比偏移量。 |
attackTargetCountPercentOffset | 浮点数 | 0.0 | 攻击目标数量的百分比偏移量。 |
示例
<!-- 作为 HediffStageDef 内部的匿名定义 -->
<attributesOffset>
<healthOffset>50</healthOffset> <!-- 生命值上限增加50 -->
<moveSpeedPercentOffset>0.15</moveSpeedPercentOffset> <!-- 移动速度增加15% -->
<attackOffset>10</attackOffset> <!-- 攻击力增加10 -->
<defensePercentOffset>-0.05</defensePercentOffset> <!-- 防御力降低5% -->
</attributesOffset>
Hediff组件定义 (<HediffCompDef>)
功能说明
Hediff组件定义(HediffCompDef)允许你为 健康定义 (<HediffDef>) 附加更复杂和动态的行为逻辑。每个组件都是一个独立的模块,可以实现特定功能,例如持续伤害、特殊效果触发、周期性事件等。
可用参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defName | 字符串 | 无 | 可选。该组件定义的唯一标识符(作为匿名定义时可省略)。 |
label | 字符串 | (空) | 可选。该组件的描述性标签。 |
description | 字符串 | (空) | 可选。该组件的详细描述。 |
compClass | 字符串 | 无 | 必需。该组件对应的C#类名。此字符串用于在代码中实例化具体的行为组件。 |
properties | 字符串 | (空) | 可选。一个自定义属性字符串,通常是JSON格式,用于向 compClass 传递配置参数,以进一步定制组件的行为。 |
示例
这是一个定义了一个持续造成伤害的Hediff组件的例子:
<!-- 作为 HediffDef 内部的匿名定义 -->
<comps>
<li>
<compClass>HediffComp_DamageOverTime</compClass>
<properties>
{"damageAmount": 2.5, "damageInterval": 1.0, "damageType": "Burn"}
</properties>
</li>
<li>
<!-- 另一个组件,例如周期性清除其他Debuff -->
<compClass>HediffComp_PeriodicCleanse</compClass>
<properties>
{"cleanseInterval": 5.0, "cleanseChance": 0.8, "targetHediffTags": ["DebuffTag"]}
</properties>
</li>
</comps>
复杂参数说明
properties 字段 (属性字符串)
- 说明:这是一个字符串字段,用于向
compClass指定的组件传递自定义的配置数据。该字符串内容通常期望是JSON格式,以便组件可以在运行时解析这些数据来配置其行为。例如,一个伤害组件可能需要damageAmount和tickInterval参数。 - 示例:
组件的C#代码会负责解析这段JSON字符串并将其映射到自身的属性上。<properties> {"key1": "value1", "key2": 123, "key3": true, "nestedObject": {"subKey": "subValue"}} </properties>
工作类定义
地图生成器
- 地图生成器工作类 (BasicTerrainMapGenerator)
- 建筑地图生成器工作类 (BuildingMapGenerator)
- 条件瓦片生成器工作类 (ConditionalTileGenerator)
- 植物地图生成器工作类 (PlantMapGenerator)
事件工作类
- 实体生成器事件工作类 (Event_EntityGenerater)
- 打开UI界面事件工作类 (Event_OpenUI)
- 播放音频事件工作类 (Event_PlayAudio)
- 物品生成事件工作类 (ItemSpawnWorkClass)
行为树节点
- AI行为树叶节点:攻击目标 (JobNode_AttackTarget)
- AI行为树叶节点:空闲 (JobNode_Idle)
- AI行为树叶节点:移动到攻击范围 (JobNode_MoveToAttackRange)
- AI行为树叶节点:徘徊 (JobNode_Wander)
地图生成器工作类 (BasicTerrainMapGenerator)
功能说明
BasicTerrainMapGenerator 是一个基础地形地图生成器工作类,它基于柏林噪声(Perlin Noise)算法来生成地图的特定区域。通过配置不同的参数,您可以控制生成瓦片的类型、密度、大小和分布,从而创建出多样化的地形,如草地、沙漠、水域或山脉。
该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。
可用参数
BasicTerrainMapGenerator 通过解析 MapGeneratorDef 中 value 字段里的 JSON 配置来工作。此 JSON 配置对应 BasicTerrainGeneratorConfig。
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
tileDefName | N/A | 字符串 | DefaultTerrainTile | 必需。符合柏林噪声条件的区域将填充的 瓦片定义 (TileDef) 的 defName。 |
threshold | N/A | 浮点数 | 0.0 | 柏林噪声的最小阈值(-1到1之间),噪声值高于此值才可能放置 tileDefName 指定的瓦片。 |
maxThreshold | N/A | 浮点数 | 1.0 | 柏林噪声的最大阈值(-1到1之间),噪声值低于此值才可能放置 tileDefName 指定的瓦片。 |
ElseTileDefName | N/A | 字符串 | 无 (null) | 可选。当柏林噪声值不满足 threshold 和 maxThreshold 范围时,该区域将填充的 瓦片定义 (TileDef) 的 defName。如果为 null 则不放置任何瓦片。 |
scale | N/A | 浮点数 | 0.1 | 柏林噪声的缩放因子。值越大,地形特征(如山脉、湖泊)的尺寸越小;值越小,特征尺寸越大。 |
offsetX | N/A | 浮点数 | 0.0 | 柏林噪声在X轴上的偏移量,用于改变噪声图案的起始位置。 |
offsetY | N/A | 浮点数 | 0.0 | 柏林噪声在Y轴上的偏移量,用于改变噪声图案的起始位置。 |
mapCellSizeX | N/A | 整数 | 100 | 地图生成区域的宽度(以单元格数量计)。 |
mapCellSizeY | N/A | 整数 | 100 | 地图生成区域的高度(以单元格数量计)。 |
targetDimension | N/A | 枚举 (字符串) | Base | 指定生成瓦片的目标地图层。详见下文**MapDimension 枚举**。 |
originX | N/A | 整数 | 0 | 地图生成区域的左上角X坐标(以单元格数量计)。 |
originY | N/A | 整数 | 0 | 地图生成区域的左上角Y坐标(以单元格数量计)。 |
示例
以下是一个 MapGeneratorDef 的示例,它使用了 BasicTerrainMapGenerator 来生成一个基础的草地地图:
<Define>
<!-- 其他 TileDef 定义... -->
<TileDef>
<defName>Grass</defName>
<label>草地</label>
<texture>tileMap_Grass</texture>
<collider>None</collider>
<tileCost>0</tileCost>
</TileDef>
<MapGeneratorDef>
<defName>GrassBase</defName>
<label>草地基础生成器</label>
<description>使用柏林噪声生成一个均匀的草地基础地形。</description>
<workClass>BasicTerrainMapGenerator</workClass>
<value>
{
"tileDefName":"Grass", // 符合条件的区域填充为"Grass"瓦片
"mapCellSizeX":100, // 生成区域宽度100格
"mapCellSizeY":100, // 生成区域高度100格
"threshold":-1.0, // 柏林噪声的最小阈值。设为-1.0表示只要噪声值不低于-1.0且不高于maxThreshold,就放置瓦片
"maxThreshold":1.0, // 柏林噪声的最大阈值。设为1.0表示只要噪声值不高于1.0且不低于threshold,就放置瓦片
"scale":7.0, // 柏林噪声缩放因子,7.0会生成较小的特征
"targetDimension":"Base", // 在基础地形层生成
"originX":0, // 从地图的(0,0)点开始生成
"originY":0
}
</value>
</MapGeneratorDef>
<MapGeneratorDef>
<defName>BasicWaterAndLand</defName>
<label>基础水陆生成器</label>
<description>使用柏林噪声生成水域和陆地交错的地形。</description>
<workClass>BasicTerrainMapGenerator</workClass>
<value>
{
"tileDefName":"Water", // 噪声在 [0.0, 0.2) 区间放置水瓦片
"ElseTileDefName":"Grass", // 噪声在其他区间放置草地瓦片
"threshold":0.0, // 噪声值大于等于0.0
"maxThreshold":0.2, // 噪声值小于0.2
"scale":0.05, // 较大的地形特征,形成大片水域和陆地
"offsetX":100.0, // 额外偏移量,使每次生成的地形不同
"offsetY":50.0,
"mapCellSizeX":200, // 生成区域宽度200格
"mapCellSizeY":200, // 生成区域高度200格
"targetDimension":"Base" // 在基础地形层生成
}
</value>
</MapGeneratorDef>
</Define>
复杂参数说明
value 字段 (JSON配置)
- 说明:
MapGeneratorDef中的value字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了BasicTerrainGeneratorConfig的所有配置参数,用于指导BasicTerrainMapGenerator的具体生成行为。您需要确保提供的JSON字符串是语法正确的。 - JSON属性与C#映射关系:
threshold:在JSON中,用于配置C#类中的MinThreshold属性。- 其他JSON属性名(如
tileDefName,scale等)与C#类中的对应属性名一致(忽略大小写差异,JSON通常使用驼峰式命名)。
- 示例:请参考上方的
MapGeneratorDef示例中value标签内的内容。
MapDimension 枚举 (地图层级)
- 说明:这是一个枚举类型,用于指定
BasicTerrainGeneratorConfig生成瓦片的目标地图层。不同的层级用于区分不同类型的地图元素,以便于渲染和逻辑处理。 - 可选值:
Base: 基础地形层,通常用于放置地面、水体等主要地形瓦片。Building: 建筑层,通常用于放置建筑结构、墙壁等可互动或阻挡的瓦片。Plant: 植物层,通常用于放置树木、草丛等植被瓦片。
- 示例:
"targetDimension":"Base""targetDimension":"Plant"
建筑地图生成器工作类 (BuildingMapGenerator)
功能说明
BuildingMapGenerator 是一个专门用于在地图上生成预定义建筑图案的工作类。它通过解析一个JSON格式的配置,将一个二维整数数组表示的图案(pattern)映射到具体的瓦片或建筑定义(mapping),然后将这些瓦片放置在地图的指定位置。这使得您可以轻松地在地图上放置复杂的预设结构,如房间、堡垒或其他定型建筑。
该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。
可用参数
BuildingMapGenerator 通过解析 MapGeneratorDef 中 value 字段里的 JSON 配置来工作。此 JSON 配置对应 BuildingGeneratorConfig。
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
defName | N/A | 字符串 | 无 | 可选。此建筑图案配置的内部名称。 |
mapping | N/A | 字典 (int -> string) | 无 | 必需。将 pattern 数组中的整数值映射到 瓦片定义 (TileDef) 或 建筑定义 (BuildingDef) 的 defName 的字典。详见下文**mapping 字段**。 |
pattern | N/A | 二维整数数组 | 无 | 必需。一个二维整数数组,表示建筑的布局图案。数组中的每个整数值都应在 mapping 字典中找到对应的定义。详见下文**pattern 字段**。 |
baseTileDefName | N/A | 字符串 | 无 | 可选。生成建筑图案所需的基底瓦片类型(例如,必须在"Grass"瓦片上建造)。如果指定,生成器会在放置建筑前检查下方瓦片是否匹配。 |
autoExpand | N/A | 布尔值 | false | 可选。如果为 true,生成器会在指定 positionX/positionY 附近寻找一个合适的空闲区域来放置建筑。如果为 false,则严格按照 positionX/positionY 放置。 |
positionX | N/A | 整数 | 无 | 必需。建筑图案放置起始位置的X坐标(左上角)。 |
positionY | N/A | 整数 | 无 | 必需。建筑图案放置起始位置的Y坐标(左上角)。 |
示例
以下是一个 MapGeneratorDef 示例,它使用了 BuildingMapGenerator 来生成一个简单的方形房间:
<Define>
<!-- 瓦片定义示例 -->
<TileDef>
<defName>Grass</defName>
<label>草地</label>
<texture>tileMap_Grass</texture>
<collider>None</collider>
<tileCost>0</tileCost>
</TileDef>
<BuildingDef>
<defName>WoodWall</defName>
<label>木墙</label>
<description>坚固的木制墙壁。</description>
<!-- ... 其他建筑属性 ... -->
</BuildingDef>
<BuildingDef>
<defName>WoodDoor</defName>
<label>木门</label>
<description>一扇普通的木门。</description>
<!-- ... 其他建筑属性 ... -->
</BuildingDef>
<BuildingDef>
<defName>Empty</defName>
<label>空</label>
<description>表示空单元格。</description>
<!-- 一个特殊的空定义,用于mapping中的0 -->
</BuildingDef>
<MapGeneratorDef>
<defName>SimpleRoomGenerator</defName>
<label>简单房间生成器</label>
<description>在指定位置生成一个木制房间。</description>
<workClass>BuildingMapGenerator</workClass>
<value>
{
"defName":"SquareWoodRoom", // 建筑图案的内部名称
"mapping":{ // 整数到瓦片/建筑定义的映射
"0":"Empty", // 0表示地板(空地)
"1":"WoodWall", // 1表示木墙
"2":"WoodDoor" // 2表示木门
},
"pattern":[ // 2D整数数组定义房间布局
[1,1,1,1,1],
[1,0,0,0,1],
[1,0,2,0,1],
[1,0,0,0,1],
[1,1,1,1,1]
],
"baseTileDefName":"Grass", // 房间必须建在草地上
"autoExpand":false, // 不自动扩展搜索区域,严格按坐标放置
"positionX":50, // 放置在地图的X坐标50
"positionY":50 // 放置在地图的Y坐标50
}
</value>
</MapGeneratorDef>
</Define>
复杂参数说明
value 字段 (JSON配置)
- 说明:
MapGeneratorDef中的value字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串容纳了BuildingGeneratorConfig的所有配置参数,用于指导BuildingMapGenerator的具体生成行为。您需要确保提供的JSON字符串是语法正确的。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
defName,mapping,pattern等)与C#类中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
- 示例:请参考上方的
MapGeneratorDef示例中value标签内的内容。
mapping 字段 (图案值到定义名称的映射)
- 说明:这是一个JSON对象,用于将
pattern数组中的整数编码映射到具体的瓦片或建筑定义的defName。在JSON中,字典的键必须是字符串,但BuildingGeneratorConfig在内部会将其解析为整数键。- 例如,
"1":"WoodWall"表示在pattern中值为1的单元格将被替换为WoodWall建筑。 - 您可以根据需要定义
0对应一个空地瓦片或特殊的Empty建筑定义。
- 例如,
- JSON定义方式:
"mapping":{ "0":"FloorTile", "1":"Wall", "2":"Door" }
pattern 字段 (建筑图案)
- 说明:这是一个JSON格式的二维数组,由多个整数数组组成,代表了建筑的行和列。每个整数值都必须在
mapping字典中找到对应的defName。- 数组的第一个维度代表行,第二个维度代表列。
- 图案的左上角(
pattern[0][0])将放置在positionX和positionY指定的地图坐标处。
- JSON定义方式:
"pattern":[ [1,1,1], [1,0,1], [1,1,1] ]
条件瓦片生成器工作类 (ConditionalTileGenerator)
功能说明
ConditionalTileGenerator 是一个高级地图生成器工作类,它允许您在地图的指定区域内,根据预设的条件(例如:下方是否存在特定瓦片类型或柏林噪声值是否达到阈值)有选择性地放置新的瓦片。这使得您可以创建更动态和有逻辑的地形生成规则,例如:在水域边缘生成芦苇,或在草地上随机分布小石块。
该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。
可用参数
ConditionalTileGenerator 通过解析 MapGeneratorDef 中 value 字段里的 JSON 配置来工作。此 JSON 配置对应 ConditionalTileGeneratorConfig。
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
outputTileDefName | N/A | 字符串 | 无 | 必需。符合所有条件时,要放置的 瓦片定义 (TileDef) 的 defName。 |
outputLayer | N/A | 字符串 | 无 | 必需。放置 outputTileDefName 瓦片的目标地图层。可选值有 "base", "building", "plant"。详见下文**outputLayer/conditionLayer 字段**。 |
conditionTileDefNames | N/A | 字符串列表 | 无 | 可选。如果非空,则只有在目标层(由 conditionLayer 指定)的当前位置存在列表中任意一个 TileDef 时,才可能生成 outputTileDefName。如果为空,则不检查此瓦片条件。 |
conditionLayer | N/A | 字符串 | 无 | 可选。当 conditionTileDefNames 非空时,检查条件瓦片的地图层。可选值有 "base", "building", "plant"。详见下文**outputLayer/conditionLayer 字段**。 |
positionX | N/A | 整数 | 无 | 必需。要进行条件检查和瓦片生成操作的矩形区域的起始X坐标(左上角)。 |
positionY | N/A | 整数 | 无 | 必需。要进行条件检查和瓦片生成操作的矩形区域的起始Y坐标(左上角)。 |
width | N/A | 整数 | 1 | 必需。生成区域的宽度(单元格数量)。 |
height | N/A | 整数 | 1 | 必需。生成区域的高度(单元格数量)。 |
usePerlinNoise | N/A | 布尔值 | false | 可选。如果为 true,则在放置瓦片前会进行柏林噪声检查。详见下文柏林噪声配置 (Perlin Noise)。 |
perlinScale | N/A | 浮点数 | 10.0 | 当 usePerlinNoise 为 true 时,柏林噪声的缩放因子(频率)。值越大,地形特征越粗糙;值越小,特征越平滑。 |
perlinThreshold | N/A | 浮点数 | 0.5 | 当 usePerlinNoise 为 true 时,柏林噪声的阈值(0.0到1.0之间)。只有柏林噪声值高于此阈值的格子才会生成瓦片。 |
perlinOffsetX | N/A | 浮点数 | 0.0 | 当 usePerlinNoise 为 true 时,柏林噪声的X轴偏移。 |
perlinOffsetY | N/A | 浮点数 | 0.0 | 当 usePerlinNoise 为 true 时,柏林噪声的Y轴偏移。 |
示例
以下是一个 MapGeneratorDef 的示例,它使用了 ConditionalTileGenerator 在特定区域的沙地上生成一些仙人掌:
<Define>
<!-- 瓦片定义示例 -->
<TileDef>
<defName>Sand</defName>
<label>沙地</label>
<texture>tileMap_Sand</texture>
</TileDef>
<!-- 注意:CactusBuildingDef 应该是 BuildingDef 类型,这里简化为 TileDef -->
<TileDef>
<defName>Cactus</defName>
<label>仙人掌</label>
<texture>tileMap_Cactus</texture>
<outputLayer>plant</outputLayer>
</TileDef>
<MapGeneratorDef>
<defName>GenerateCactiOnSand</defName>
<label>在沙地上生成仙人掌</label>
<description>在地图特定沙地区域内随机生成仙人掌。</description>
<workClass>ConditionalTileGenerator</workClass>
<value>
{
"outputTileDefName":"Cactus", // 生成仙人掌
"outputLayer":"plant", // 放置在植物层
"conditionTileDefNames":["Sand"], // 条件:下方必须是沙地
"conditionLayer":"base", // 检查基础层是否有沙地
"positionX":10, // 检查区域的起始X坐标
"positionY":10, // 检查区域的起始Y坐标
"width":50, // 检查区域宽度50格
"height":50, // 检查区域高度50格
"usePerlinNoise":true, // 使用柏林噪声进行随机性检查
"perlinScale":20.0, // 柏林噪声频率,数值越大越粗糙(点状分布)
"perlinThreshold":0.6, // 只有噪声值高于0.6才生成仙人掌,控制密度
"perlinOffsetX":100.0, // 噪声X轴偏移
"perlinOffsetY":200.0 // 噪声Y轴偏移
}
</value>
</MapGeneratorDef>
</Define>
复杂参数说明
value 字段 (JSON配置)
- 说明:
MapGeneratorDef中的value字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了ConditionalTileGeneratorConfig的所有配置参数,用于指导ConditionalTileGenerator的具体生成行为。您需要确保提供的JSON字符串是语法正确的。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
outputTileDefName,conditionTileDefNames等)与C#类中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
- 示例:请参考上方的
MapGeneratorDef示例中value标签内的内容。
outputLayer / conditionLayer 字段 (地图层级字符串)
- 说明:这两个字段都用于指定地图的层级。这是一个字符串值,而不是一个枚举数字。
- 可选值:
"base": 基础地形层,用于放置地面、水体等。"building": 建筑层,用于放置建筑结构、墙壁等。"plant": 植物层,用于放置树木、草丛等植被。
- 示例:
"outputLayer":"plant""conditionLayer":"base"
conditionTileDefNames 字段 (条件瓦片定义列表)
- 说明:这是一个JSON数组,包含一个或多个 瓦片定义 (
TileDef) 的defName字符串。当ConditionalTileGenerator检查一个格子时,如果该格子在conditionLayer指定的层上拥有此列表中任意一个defName对应的瓦片,则条件检查通过。 - JSON定义方式:
上述配置表示,如果下方瓦片是“Grass”、“Dirt”或“Sand”中的任意一种,则条件满足。"conditionTileDefNames":["Grass", "Dirt", "Sand"]
柏林噪声配置 (usePerlinNoise, perlinScale, perlinThreshold, perlinOffsetX, perlinOffsetY)
- 说明:当
usePerlinNoise设置为true时,生成器会在每个候选位置计算一个柏林噪声值。只有当这个噪声值高于perlinThreshold时,瓦片才会被放置。这为生成过程引入了自然的随机性和分布模式。perlinScale:控制柏林噪声的“粒度”。值越大,噪声图案变化越快,特征越小;值越小,图案变化越慢,特征越大。perlinThreshold:决定瓦片放置的密度。较高的阈值意味着只有噪声值非常高的位置才能放置瓦片,从而导致稀疏分布;较低的阈值则会生成更密集的瓦片。perlinOffsetX,perlinOffsetY:用于偏移柏林噪声的起始点,可以改变生成图案的位置,每次生成都可以使用不同的偏移值来获得不同的随机布局。
- 示例:
"usePerlinNoise":true, "perlinScale":15.0, "perlinThreshold":0.7, "perlinOffsetX":50.0, "perlinOffsetY":120.0
植物地图生成器工作类 (PlantMapGenerator)
功能说明
PlantMapGenerator 是一个专门用于在地图上生成植物(如草丛、树木、灌木等)的工作类。它结合了柏林噪声(Perlin Noise)和概率密度来控制植物的分布,并可以指定植物生长的基础瓦片类型。这使得您可以创建茂密的森林、稀疏的草地或只在特定土壤上生长的植被。
该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。
可用参数
PlantMapGenerator 通过解析 MapGeneratorDef 中 value 字段里的 JSON 配置来工作。此 JSON 配置对应 PlantGeneratorConfig。
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
tileDefName | N/A | 字符串 | DefaultPlantTile | 必需。要生成的 植物瓦片定义 (TileDef) 的 defName。通常此瓦片定义会放置在 plant 层。 |
scale | N/A | 浮点数 | 0.08 | 柏林噪声的缩放因子。值越大,植物群落分布越细碎;值越小,群落范围越大越连贯。 |
threshold | N/A | 浮点数 | 0.3 | 柏林噪声的阈值(-1到1之间)。只有柏林噪声值高于此阈值的格子才优先考虑生成植物。 |
density | N/A | 浮点数 | 0.6 | 植物生成概率(0.0到1.0之间)。在所有条件(包括柏林噪声和基础瓦片)都满足的情况下,该格子最终生成植物的概率。 |
offsetX | N/A | 浮点数 | 0.0 | 柏林噪声在X轴上的偏移量,用于改变噪声图案的起始位置。 |
offsetY | N/A | 浮点数 | 0.0 | 柏林噪声在Y轴上的偏移量,用于改变噪声图案的起始位置。 |
requiredBaseTileDefNames | N/A | 字符串列表 | 无 (null) | 可选。一个字符串列表,包含植物必须生长其上的 基础瓦片定义 (TileDef) 的 defName。如果指定,只有当当前位置的基础层瓦片是列表中任意一个时,才可能生成植物。如果为空,则不检查此条件。 |
mapCellSizeX | N/A | 整数 | 100 | 地图生成区域的宽度(以单元格数量计)。 |
mapCellSizeY | N/A | 整数 | 100 | 地图生成区域的高度(以单元格数量计)。 |
preventOverlap | N/A | 布尔值 | true | 可选。如果为 true,生成器会避免在已经有植物瓦片的格子上再次生成植物。 |
示例
以下是一个 MapGeneratorDef 的示例,它使用了 PlantMapGenerator 在草地和泥土上生成一些稀疏的树木:
<Define>
<!-- 瓦片定义示例 -->
<TileDef>
<defName>Grass</defName>
<label>草地</label>
<texture>tileMap_Grass</texture>
<collider>None</collider>
<tileCost>0</tileCost>
</TileDef>
<TileDef>
<defName>Dirt</defName>
<label>泥土</label>
<texture>tileMap_Dirt</texture>
<collider>None</collider>
<tileCost>0</tileCost>
</TileDef>
<TileDef>
<defName>TreePine</defName>
<label>松树</label>
<texture>plant_TreePine</texture>
<outputLayer>plant</outputLayer> <!-- 植物通常放置在 plant 层 -->
</TileDef>
<MapGeneratorDef>
<defName>GenerateSparsePineForest</defName>
<label>生成稀疏松树林</label>
<description>在草地和泥土上生成稀疏的松树林。</description>
<workClass>PlantMapGenerator</workClass>
<value>
{
"tileDefName":"TreePine", // 要生成的植物是松树
"scale":0.05, // 柏林噪声缩放因子,值较小,形成更大的森林斑块
"threshold":0.2, // 柏林噪声阈值,控制整体分布区域
"density":0.3, // 密度0.3,表示较为稀疏的树木
"offsetX":10.0, // 噪声X轴偏移
"offsetY":20.0, // 噪声Y轴偏移
"requiredBaseTileDefNames":["Grass", "Dirt"], // 必须生长在草地或泥土上
"mapCellSizeX":200, // 区域宽度200格
"mapCellSizeY":200, // 区域高度200格
"preventOverlap":true // 防止树木重叠
}
</value>
</MapGeneratorDef>
</Define>
复杂参数说明
value 字段 (JSON配置)
- 说明:
MapGeneratorDef中的value字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了PlantGeneratorConfig的所有配置参数,用于指导PlantMapGenerator的具体生成行为。您需要确保提供的JSON字符串是语法正确的。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
tileDefName,scale等)与C#类中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
- 示例:请参考上方的
MapGeneratorDef示例中value标签内的内容。
requiredBaseTileDefNames 字段 (所需基础瓦片定义列表)
- 说明:这是一个JSON数组,包含一个或多个 瓦片定义 (
TileDef) 的defName字符串。PlantMapGenerator在尝试在某个格子生成植物之前,会检查该格子在基础层的瓦片是否与此列表中的任意一个defName匹配。 - JSON定义方式:
上述配置表示,植物只会在 "ForestSoil" 或 "FertileLand" 瓦片上生成。如果此列表为空或未指定,则不进行基础瓦片检查。"requiredBaseTileDefNames":["ForestSoil", "FertileLand"]
柏林噪声配置 (scale, threshold, offsetX, offsetY)
- 说明:这些参数用于控制柏林噪声的生成和应用,从而影响植物的分布。
scale:控制噪声的“频率”或“粒度”。- 值越大 (例如 0.5-1.0):柏林噪声图案变化迅速,导致生成的植物群落更小、更分散、更“点状”。适合生成稀疏分布的小草丛或零星的野花。
- 值越小 (例如 0.01-0.1):柏林噪声图案变化平缓,导致生成的植物群落更大、更连贯。适合生成大片森林或草地。
threshold:柏林噪声的阈值(-1到1)。只有当柏林噪声值高于此阈值时,该位置才被认为是适合生成植物的区域。- 值越高 (接近1):只有噪声值非常高的“峰值”区域才能生成植物,导致植物非常稀疏,只出现在少数高点。
- 值越低 (接近-1):几乎所有区域的噪声值都可能高于阈值,导致植物覆盖范围更广。
offsetX,offsetY:用于在地图上“移动”柏林噪声图案的起始点。每次生成地图或在不同区域生成植物时,改变这些值可以获得不同的随机分布模式,避免重复。
- 总而言之:
scale决定了植物群落的大小和连续性,threshold决定了植物群落的密集程度和覆盖范围。density在满足柏林噪声条件后,再次引入一个随机性层,进一步稀释植物的实际生成数量。 - 示例:
"scale":0.1, "threshold":0.4, "offsetX":500.0, "offsetY":300.0
实体生成器事件工作类 (Event_EntityGenerater)
功能说明
Event_EntityGenerater 是一个功能强大的事件工作类,它用于在游戏世界中生成各种类型的实体(如角色、怪物、建筑、物品等)。此事件配置高度灵活,允许您指定要生成的实体数量、哪些实体定义可供选择(将从中随机选取),以及实体生成的具体位置类型和相关参数。它支持在地图内外、特定坐标周围、目标实体周围或随机位置生成实体,为游戏事件、环境填充和动态内容生成提供了核心支持。
该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。
可用参数
Event_EntityGenerater 通过解析 EventDef 中 parameter 字段里的 JSON 配置来工作。此 JSON 配置对应 EntityGenerateConfig 数据结构。
EntityGenerateConfig 字段列表
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
DefinitionsToChooseFrom | N/A | List<EntityDefinitionEntry> | 无 | 必需。一个列表,包含可供随机选择生成的实体定义条目。每个条目都指定一个实体 defName 和其 DefType。 |
Count | N/A | 整数 | 1 | 可选。要生成的实体总数。每次调用 Run 时,系统将尝试生成该数量的实体。 |
LocationType | N/A | EntitySpawnLocationType | None | 可选。指定实体生成的位置类型。请参见下方的 EntitySpawnLocationType 枚举说明。 |
CenterCoordinates | N/A | Vector3 | (0,0,0) | 可选。仅当 LocationType 为 AroundSpecificCoordinates 时生效。指定生成区域的中心坐标。 |
Radius | N/A | 浮点数 | 10.0f | 可选。仅当 LocationType 为 AroundSpecificCoordinates 或 AroundTargetEntity 时生效。指定以中心点或目标实体为圆心的生成半径。 |
BuildingTypeDefName | N/A | 字符串 | null | 可选。仅当 LocationType 为 InsideSpecificBuildingType 时生效。指定目标建筑的建筑定义 (BuildingDef) defName。当前未实现。 |
TargetFactionDefName | N/A | 字符串 | null | 可选。仅当 LocationType 为 AroundTargetEntity 时生效。指定目标派系的派系定义 (FactionDef) defName。系统将会在该派系的随机一个实体周围生成。 |
SpawnPointTileMapDefName | N/A | 字符串 | null | 可选。仅当 LocationType 为 AtPredefinedSpawnPoint 时生效。指定预定义生成点的 defName。当前未实现。 |
OffMapOffset | N/A | 浮点数 | 5.0f | 可选。仅当 LocationType 为 OffMap 时生效。指定实体应在地图边界之外的额外偏移量。 |
EntityDefinitionEntry 内部字段列表 (在 DefinitionsToChooseFrom 列表中使用)
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
DefName | N/A | 字符串 | 无 | 必需。要生成的具体实体定义的 defName。 |
DefType | N/A | EntityDefTypeIdentifier | None | 必需。此 DefName 对应的实体定义类型。请参见下方的 EntityDefTypeIdentifier 枚举说明。 |
EntitySpawnLocationType (枚举)
指定实体生成的可能位置类型。
None(0): 未指定或无效的生成位置类型。OffMap: 在地图的可玩区域边界之外按随机方向生成实体。InsideSpecificBuildingType: 在指定类型建筑的内部或附近生成实体。当前未实现。AroundSpecificCoordinates: 在指定CenterCoordinates周围Radius范围内生成实体。AroundTargetEntity: 在指定TargetFactionDefName派系中的一个随机实体周围Radius范围内生成实体。RandomlyOnMap: 在地图上的随机可生成点生成实体。AtPredefinedSpawnPoint: 在预定义的生成点(通过SpawnPointTileMapDefName指定)生成实体。当前未实现。
EntityDefTypeIdentifier (枚举)
指定支持的实体定义类型标识符,用于 EntityDefinitionEntry 中。
None(0): 未指定或无效的实体定义类型。CharacterDef: 角色定义类型 (例如:NPC、玩家)。MonsterDef: 怪物定义类型 (例如:敌人、野兽)。BuildingDef: 建筑定义类型 (例如:墙壁、工作台)。BulletDef: 子弹定义类型 (例如:投射物)。ItemDef: 物品定义类型 (用于可拾取物,例如:材料、普通工具)。WeaponDef: 武器定义类型 (继承自ItemDef的特殊物品,例如:刀剑、弓箭)。
示例
以下是 EventDef 的示例,展示了 Event_EntityGenerater 的不同用法:
<Define>
<!-- 假设已有 Character_Villager, Monster_Wolf, Item_GoldBar 等 [实体定义](DefineTypes.md) -->
<!-- 示例1: 在地图外生成3只狼 -->
<EventDef>
<defName>SpawnWolvesOffMap</defName>
<label>在地图外生成狼</label>
<description>在地图边界外生成3只野狼。</description>
<workClass>Event_EntityGenerater</workClass>
<parameter>
{
"DefinitionsToChooseFrom": [
{"DefName": "Monster_Wolf", "DefType": "MonsterDef"}
],
"Count": 3,
"LocationType": "OffMap",
"OffMapOffset": 8.0
}
</parameter>
</EventDef>
<!-- 示例2: 在特定坐标附近生成单个村民 -->
<EventDef>
<defName>SpawnVillagerAtCamp</defName>
<label>在营地生成村民</label>
<description>在指定营地坐标附近生成一个村民。</description>
<workClass>Event_EntityGenerater</workClass>
<parameter>
{
"DefinitionsToChooseFrom": [
{"DefName": "Character_Villager", "DefType": "CharacterDef"}
],
"Count": 1,
"LocationType": "AroundSpecificCoordinates",
"CenterCoordinates": {"x": 50.0, "y": 30.0, "z": 0.0},
"Radius": 5.0
}
</parameter>
</EventDef>
<!-- 示例3: 在玩家派系实体周围生成2个金条 (随机选择) -->
<EventDef>
<defName>PlayerFactionGoldDrop</defName>
<label>玩家派系金条掉落</label>
<description>在玩家派系中的一个随机实体周围生成2个金条。</description>
<workClass>Event_EntityGenerater</workClass>
<parameter>
{
"DefinitionsToChooseFrom": [
{"DefName": "Item_GoldBar", "DefType": "ItemDef"}
],
"Count": 2,
"LocationType": "AroundTargetEntity",
"TargetFactionDefName": "Faction_Player",
"Radius": 3.0
}
</parameter>
</EventDef>
<!-- 示例4: 在地图上随机位置生成一棵树 (建筑) -->
<EventDef>
<defName>SpawnRandomTree</defName>
<label>随机生成树</label>
<description>在地图上的随机位置生成一棵树。</description>
<workClass>Event_EntityGenerater</workClass>
<parameter>
{
"DefinitionsToChooseFrom": [
{"DefName": "Building_Tree", "DefType": "BuildingDef"}
],
"Count": 1,
"LocationType": "RandomlyOnMap"
}
</parameter>
</EventDef>
<!-- 示例5: 混合生成:3个敌人或2个宝箱,在地图任意位置随机生成 -->
<EventDef>
<defName>MixedRandomGeneration</defName>
<label>混合随机生成</label>
<description>在地图随机位置生成3个怪物(可能狼或熊)或2个宝箱。</description>
<workClass>Event_EntityGenerater</workClass>
<parameter>
{
"DefinitionsToChooseFrom": [
{"DefName": "Monster_Wolf", "DefType": "MonsterDef"},
{"DefName": "Monster_Bear", "DefType": "MonsterDef"},
{"DefName": "Item_TreasureChest", "DefType": "ItemDef"}
],
"Count": 3,
"LocationType": "RandomlyOnMap"
}
</parameter>
</EventDef>
</Define>
复杂参数说明
parameter 字段 (JSON配置)
- 说明:
EventDef中的parameter字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了EntityGenerateConfig的所有配置参数,用于指导Event_EntityGenerater的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合EntityGenerateConfig的结构。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
DefinitionsToChooseFrom,Count等)与C#内部数据类EntityGenerateConfig中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
Vector3的JSON表示: 在JSON中,Vector3类型的字段需要以一个包含x,y,z三个浮点数字段的JSON对象形式表示。- 例如:
"CenterCoordinates": { "x": 50.0, "y": 30.0, "z": 0.0 }
- 例如:
- 枚举值的JSON表示:
在JSON中,所有枚举类型(如
LocationType,DefType)都应以其字符串名称来表示。- 例如:
"LocationType": "OffMap" - 例如:
"DefType": "MonsterDef"
- 例如:
DefinitionsToChooseFrom 字段 (实体定义列表 - 必填)
- 说明:这是一个必需的列表,其中包含一个或多个
EntityDefinitionEntry对象。每次生成实体时,Event_EntityGenerater会从这个列表中随机选择一个实体定义来生成。 EntityDefinitionEntry结构:每个对象都需要包含:"DefName"(字符串):具体的实体定义名称(例如 "Monster_Wolf"),此名称必须在 实体定义 (Define) 中能够找到对应条目。"DefType"(EntityDefTypeIdentifier枚举):此DefName所属的实体定义类型(例如 "MonsterDef")。这是为了帮助系统正确查找并实例化对应的定义。
LocationType 字段 (生成位置类型 - 关键)
- 说明:这个字段是实体生成位置逻辑的核心。根据您选择的
LocationType,其他相关的定位参数(如CenterCoordinates,Radius,TargetFactionDefName等)才会生效。请仔细查阅上述EntitySpawnLocationType枚举的说明,并根据您的需求选择合适的位置类型。 - 当前未实现的类型:请注意
InsideSpecificBuildingType和AtPredefinedSpawnPoint当前未实现,如果使用这些类型,事件将无法正常生成实体并返回错误。
打开UI界面事件工作类 (Event_OpenUI)
功能说明
Event_OpenUI 是一个事件工作类,它的主要功能是根据给定的名称打开一个用户界面(UI)。这使得您可以在游戏中的特定事件发生时,弹出预设的UI面板,例如:完成任务后打开奖励界面、点击NPC时显示对话框、或者触发特定条件时打开商店或背包界面。
该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。
可用参数
Event_OpenUI 通过解析 EventDef 中 parameter 字段里的 JSON 配置来工作。此 JSON 配置对应一个内部的数据结构。
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
uiName | N/A | 字符串 | 无 | 必需。要打开的UI界面的内部名称。此名称应与游戏UI系统注册的某个界面名称精确匹配。 |
示例
以下是一个 EventDef 示例,展示了如何使用 Event_OpenUI 在事件触发时打开一个名为“PlayerInventoryUI”的玩家背包界面:
<Define>
<EventDef>
<defName>OpenPlayerInventoryEvent</defName>
<label>打开玩家背包</label>
<description>触发时打开玩家的背包界面。</description>
<workClass>Event_OpenUI</workClass>
<parameter>
{
"uiName": "PlayerInventoryUI" // 指定要打开的UI名称
}
</parameter>
</EventDef>
<EventDef>
<defName>OpenSettingsPanelEvent</defName>
<label>打开设置面板</label>
<description>触发时打开游戏的设置面板。</description>
<workClass>Event_OpenUI</workClass>
<parameter>
{
"uiName": "SettingsPanel" // 指定要打开的UI名称
}
</parameter>
</EventDef>
</Define>
复杂参数说明
parameter 字段 (JSON配置)
- 说明:
EventDef中的parameter字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了Event_OpenUI的所有配置参数,用于指导其具体行为。您需要确保提供的JSON字符串是语法正确的。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
uiName)与C#内部数据类中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
- 示例:请参考上方的
EventDef示例中parameter标签内的内容。
uiName 字段 (UI界面名称)
- 说明:此字段是一个字符串,其值必须与游戏UI系统中实际注册的UI界面的唯一标识符(名称)精确匹配。如果提供了不正确的名称,系统将无法找到并打开对应的界面。
- 命名约定:
uiName的具体命名约定取决于游戏UI框架的实现。通常建议使用清晰、一致的名称,例如MainMenuUI、QuestLogPanel、ShopWindow等。 - 示例:
"uiName": "GameHelpDialog"
播放音频事件工作类 (Event_PlayAudio)
功能说明
Event_PlayAudio 是一个事件工作类,用于在游戏中的特定时刻播放音频片段。它提供了丰富的配置选项,允许您精确控制音频的播放方式,包括音量、是否循环、空间混合(2D或3D音效)、播放延迟,以及是否将音效关联到触发事件的实体上,或在播放结束后自动销毁。这使得您可以为各种游戏事件(如用户界面交互、技能施放、环境音效、背景音乐片段等)添加动态的听觉反馈。
该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。
可用参数
Event_PlayAudio 通过解析 EventDef 中 parameter 字段里的 JSON 配置来工作。此 JSON 配置对应 AudioEventConfig。
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
audioClipName | N/A | 字符串 | 无 | 必需。要播放的音频资源或 音频定义 (AudioDef) 的 defName。系统将通过此名称获取实际的音频数据。 |
volume | N/A | 浮点数 | 1.0 | 播放音量(0.0到1.0之间)。1.0 为最大音量。 |
loop | N/A | 布尔值 | false | 如果为 true,音频将循环播放直到被其他逻辑停止。 |
spatialBlend | N/A | 浮点数 | 0.0 | 空间混合因子(0.0到1.0之间)。0.0 为完全2D音效(不受听者位置影响),1.0 为完全3D音效(受听者位置和距离影响)。 |
attachToInitiator | N/A | 布尔值 | true | 如果存在触发此事件的实体(发起者),当此项为 true 时,音频播放器会尝试附加到该发起者上,使其成为一个3D音源(即使 spatialBlend 为 0.0,也依然会跟随发起者移动而移动)。 |
delay | N/A | 浮点数 | 0.0 | 播放前的延迟秒数。 |
destroyAfterPlay | N/A | 布尔值 | true | 如果是非循环播放的音效,并且系统临时创建了一个音频源来播放它,当此项为 true 时,会在播放结束后自动销毁这个临时的音频源以节省资源。 |
示例
以下是 EventDef 的示例,展示了 Event_PlayAudio 的不同用法:
<Define>
<!-- 假设已有 Sound_ButtonClick 和 Sound_AmbientWind 等 [音频定义 (AudioDef)](AudioDef.md) -->
<EventDef>
<defName>PlayButtonClickSound</defName>
<label>播放按钮点击音效</label>
<description>在UI点击时播放短促的按钮点击音效。</description>
<workClass>Event_PlayAudio</workClass>
<parameter>
{
"audioClipName": "Sound_ButtonClick", // 要播放的音频定义名
"volume": 0.8, // 音量为0.8
"loop": false, // 不循环
"spatialBlend": 0.0, // 2D音效
"attachToInitiator": false // UI音效通常不依附于发起者
}
</parameter>
</EventDef>
<EventDef>
<defName>PlayAmbientWindSound</defName>
<label>播放环境风声</label>
<description>在地图特定区域播放循环环境风声。</description>
<workClass>Event_PlayAudio</workClass>
<parameter>
{
"audioClipName": "Sound_AmbientWind", // 播放环境风声
"volume": 0.5, // 音量为0.5
"loop": true, // 循环播放
"spatialBlend": 1.0, // 3D音效,受位置影响
"attachToInitiator": true // 依附于事件发起者(例如一个风源实体)
}
</parameter>
</EventDef>
<EventDef>
<defName>PlayDelayedWarningSound</defName>
<label>播放延迟警告音效</label>
<description>在5秒延迟后播放一个警告音效。</description>
<workClass>Event_PlayAudio</workClass>
<parameter>
{
"audioClipName": "Sound_Warning",
"volume": 1.0,
"delay": 5.0, // 延迟5秒播放
"destroyAfterPlay": true // 播放完成后自动销毁
}
</parameter>
</EventDef>
</Define>
复杂参数说明
parameter 字段 (JSON配置)
- 说明:
EventDef中的parameter字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了AudioEventConfig的所有配置参数,用于指导Event_PlayAudio的具体行为。您需要确保提供的JSON字符串是语法正确的。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
audioClipName,volume等)与C#内部数据类中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
- 示例:请参考上方的
EventDef示例中parameter标签内的内容。
volume 和 spatialBlend 字段 (浮点数范围)
- 说明:这两个字段都接受浮点数,但其值应限制在特定的有效范围内。
volume:值应介于0.0(静音)到1.0(最大音量)之间。超出此范围的值可能会被截断或导致非预期行为。spatialBlend:值应介于0.0(完全2D)到1.0(完全3D)之间。
- 示例:
"volume": 0.75, // 75%音量 "spatialBlend": 0.5 // 混合音效,2D与3D各一半
loop, attachToInitiator, destroyAfterPlay 字段 (布尔值开关)
- 说明:这些字段是布尔值开关,接受
true或false。loop:控制音频是否重复播放。attachToInitiator:当一个实体触发事件时,这个选项决定了音频源是否附加到该实体上。这常用于使音效跟随实体移动,或使3D音效从实体位置发出。destroyAfterPlay:主要用于非循环音效。如果为true,系统在播放完毕后会自动清理临时创建的音频源。如果为false,则需要其他逻辑手动清理,否则可能造成资源泄露。
- 示例:
"loop": true, "attachToInitiator": true, "destroyAfterPlay": false
物品生成事件工作类 (Event_ItemGenerater)
功能说明
Event_ItemGenerater 是一个用于在游戏世界中生成物品的事件工作类。它允许您指定要生成的物品类型及其精确的生成位置。这对于实现诸如掉落物品、奖励物品、场景互动生成物品等功能非常有用。
该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。
可用参数
Event_ItemGenerater 通过解析 EventDef 中 parameter 字段里的 JSON 配置来工作。此 JSON 配置对应 ItemSpawnData 数据结构。
ItemSpawnData 字段列表
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
itemDefName | N/A | 字符串 | 无 | 必需。要生成的物品的定义名称 (ItemDef 的 defName)。例如:"IRON_SWORD"。 |
position | N/A | Vector3 | null | 可选。物品生成的绝对世界坐标。如果提供了此字段,将优先使用此位置。 |
relativeOffset | N/A | Vector3 | null | 可选。物品相对于事件触发者 (initiator) 的偏移坐标。仅当 initiator 存在且 position 未设置时生效。 |
示例
以下是 EventDef 的示例,展示了 Event_ItemGenerater 的不同用法:
<Define>
<!-- 假设已有 ItemDef: WoodenSword, HealthPotion -->
<!-- 示例1: 在玩家击败怪物后掉落一个木剑 (相对坐标) -->
<EventDef>
<defName>DropWoodenSwordOnDefeat</defName>
<label>掉落木剑</label>
<description>在怪物死亡位置附近掉落一把木剑。</description>
<workClass>Event_ItemGenerater</workClass>
<parameter>
{
"itemDefName": "WoodenSword",
"relativeOffset": {"x": 0.5, "y": 0.0, "z": 0.0}
}
</parameter>
</EventDef>
<!-- 示例2: 在地图的固定坐标生成一个生命药水 -->
<EventDef>
<defName>SpawnHealthPotionAtLocation</defName>
<label>生成生命药水</label>
<description>在地图的特定区域生成一个生命药水。</description>
<workClass>Event_ItemGenerater</workClass>
<parameter>
{
"itemDefName": "HealthPotion",
"position": {"x": 10.0, "y": 5.0, "z": 0.0}
}
</parameter>
</EventDef>
<!-- 示例3: 在没有任何指定位置的情况下,直接在触发者实体上生成一个物品 (使用触发者位置) -->
<EventDef>
<defName>SpawnKeyOnInitiator</defName>
<label>生成钥匙</label>
<description>在触发表格的实体所在位置生成一把钥匙。</description>
<workClass>Event_ItemGenerater</workClass>
<parameter>
{
"itemDefName": "Key_Dungeon"
}
</parameter>
</EventDef>
</Define>
复杂参数说明
parameter 字段 (JSON配置)
- 说明:
EventDef中的parameter字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了ItemSpawnData的所有配置参数,用于指导Event_ItemGenerater的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合ItemSpawnData的结构。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
itemDefName,position等)与C#内部数据类ItemSpawnData中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
位置 (position, relativeOffset) 逻辑
物品的生成位置遵循以下优先级和逻辑:
- 绝对位置 (
position):如果position字段被设定,则物品将精确地生成在该世界坐标。这是定位的最高优先级。 - 相对偏移 (
relativeOffset):如果position未设置,但relativeOffset字段被设定,并且事件有一个initiator(触发者实体),则物品将生成在initiator的位置加上relativeOffset。 - 触发者位置:如果
position和relativeOffset都未设置,但事件有一个initiator,则物品将生成在initiator的当前位置。 - 错误处理:如果上述所有条件均不满足(即未提供
position,没有relativeOffset或没有initiator),则物品生成会失败并抛出异常,因为系统无法确定一个有效的生成位置。
Vector3 的JSON表示
- 在JSON中,
Vector3类型的字段(如position和relativeOffset)需要以一个包含x,y,z三个浮点数字段的JSON对象形式表示。 - 例如:
"position": { "x": 10.0, "y": 5.0, "z": 0.0 }
消息显示事件工作类 (Event_MessageWorkClass)
功能说明
Event_MessageWorkClass 是一个用于在游戏界面上显示文本消息的事件工作类。它提供灵活的配置选项,允许您定义消息的内容、显示类别(决定其在UI上的呈现方式)、文本颜色以及持续显示的时长。这使得开发者能够通过游戏事件轻松地向玩家传达提示、警告、剧情信息或任何其他文本内容。
该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。
可用参数
Event_MessageWorkClass 通过解析 EventDef 中 parameter 字段里的 JSON 配置来工作。此 JSON 配置对应 MessageData。
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
message | N/A | 字符串 | 无 | 必需。要显示的消息文本内容。 |
type | N/A | PromptDisplayCategory | 无 | 必需。消息的显示类别,决定了消息在UI中的呈现方式。请参见下方的 PromptDisplayCategory 枚举说明。 |
color | N/A | 字符串 | null | 可选。消息文本的颜色。必须是一个有效的HTML颜色字符串格式(例如 "#RRGGBB" 或 "#RRGGBBAA")。如果省略,将使用系统默认颜色。 |
showTime | N/A | 浮点数 | null | 可选。消息在屏幕上显示的持续时长(秒)。如果省略,将使用 DisplayMessage API 的默认时长(通常为3秒)。 |
PromptDisplayCategory (枚举)
PromptDisplayCategory 枚举定义了消息的不同显示类别,这将影响消息在游戏界面上的具体呈现方式(例如位置、大小、动画等)。
- 请查阅具体游戏UI系统文档以获取
PromptDisplayCategory的详细枚举值及其对应的显示效果。- 示例可能的枚举值(实际请以游戏代码为准):
SystemMessage: 系统通知,通常位于屏幕中央或顶部。Warning: 警告信息,可能以黄色或红色高亮显示。QuestUpdate: 任务更新提示。Dialogue: 对话或剧情文本。FloatingText: 浮动在实体上方的文本,如伤害数字。
- 示例可能的枚举值(实际请以游戏代码为准):
示例
以下是 EventDef 的示例,展示了 Event_MessageWorkClass 的不同用法:
<Define>
<!-- 假设 PromptDisplayCategory 枚举类型包含 SystemMessage, Warning, QuestUpdate 值 -->
<!-- 示例1: 显示一个普通的系统消息 -->
<EventDef>
<defName>ShowSystemWelcomeMessage</defName>
<label>显示欢迎消息</label>
<description>在游戏开始时显示一条欢迎系统消息。</description>
<workClass>Event_MessageWorkClass</workClass>
<parameter>
{
"message": "欢迎来到奇幻世界!",
"type": "SystemMessage"
}
</parameter>
</EventDef>
<!-- 示例2: 显示一个红色的警告消息,持续5秒 -->
<EventDef>
<defName>ShowCriticalWarning</defName>
<label>显示严重警告</label>
<description>在发生严重错误时显示红色警告。</description>
<workClass>Event_MessageWorkClass</workClass>
<parameter>
{
"message": "危险!敌人正在逼近!",
"type": "Warning",
"color": "#FF0000",
"showTime": 5.0
}
</parameter>
</EventDef>
<!-- 示例3: 显示一个绿色的任务更新消息 -->
<EventDef>
<defName>ShowQuestCompleted</defName>
<label>显示任务完成提示</label>
<description>任务完成后显示绿色提示。</description>
<workClass>Event_MessageWorkClass</workClass>
<parameter>
{
"message": "主线任务:探索之始 完成!",
"type": "QuestUpdate",
"color": "#00FF00"
}
</parameter>
</EventDef>
</Define>
复杂参数说明
parameter 字段 (JSON配置)
- 说明:
EventDef中的parameter字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了MessageData的所有配置参数,用于指导Event_MessageWorkClass的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合MessageData的结构。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
message,type等)与C#内部数据类MessageData中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
- 枚举值的JSON表示:
在JSON中,枚举类型
PromptDisplayCategory的值应以其字符串名称来表示。- 例如:
"type": "SystemMessage"
- 例如:
color 字段 (HTML颜色字符串)
- 说明:如果需要为消息文本指定颜色,可以使用
color字段。这个字段的值必须是有效的HTML颜色字符串。- 支持的格式:
"#RRGGBB":六位十六进制RGB值,例如"#FF0000"(红色)。"#RRGGBBAA":八位十六进制RGBA值(包含透明度),例如"#00FF0080"(半透明绿色)。
- 注意事项:如果您提供的颜色字符串格式不正确,
Event_MessageWorkClass在初始化时会报错,导致事件无法运行。
- 支持的格式:
临时动画事件工作类 (Event_TemporaryAnimationWorkClass)
功能说明
Event_TemporaryAnimationWorkClass 是一个功能强大的事件工作类,用于在游戏世界或UI界面上播放各种临时动画效果。它支持多种动画内容类型(文本、精灵序列和DrawNode定义),并提供了灵活的配置选项,允许您精确控制动画的位置、生命周期、帧率以及是否将其附加到触发事件的实体上。这使得开发者能够通过事件系统轻松地实现诸如飘字、特效、物品拾取提示、短暂的视觉反馈等效果。
该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。
可用参数
Event_TemporaryAnimationWorkClass 通过解析 EventDef 中 parameter 字段里的 JSON 配置来工作。此 JSON 配置对应 TemporaryAnimationData 数据结构。
TemporaryAnimationData 字段列表
| JSON参数名 | XML参数名 (N/A) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
contentType | N/A | AnimationContentType | 无 | 必需。动画内容的类型。决定了使用 textContent、spriteNames 或 drawNodeDefName 字段。请参见下方的 AnimationContentType 枚举说明。 |
isUIAnimation | N/A | 布尔 | false | 可选。指示动画是否作为UI元素显示在Canvas上。如果为 true,动画将适配屏幕坐标。 |
textContent | N/A | 字符串 | null | 可选。当 contentType 为 Text 时使用。动画的文本内容。 |
spriteNames | N/A | 字符串数组 (string[]) | null | 可选。当 contentType 为 Sprite 时使用。组成动画的精灵资源名称数组,将按顺序播放以形成帧动画。 |
drawNodeDefName | N/A | 字符串 | null | 可选。当 contentType 为 DrawNode 时使用。DrawNode定义 (DrawNodeDef) 的 defName,用于渲染复杂图像或粒子效果。 |
position | N/A | Vector3 | null | 可选。动画的绝对世界初始位置。如果设置,将优先使用此位置。 |
relativeOffset | N/A | Vector3 | null | 可选。动画相对于事件触发者 (initiator) 的偏移坐标。仅在 initiator 存在且 position 未设置时生效。 |
parentToInitiator | N/A | 布尔 | false | 可选。指示动画是否应设置为事件触发者 (initiator) 的子对象。如果触发者不存在,此设置无效。 |
lifeTime | N/A | 浮点数 | 3.0f | 可选。动画的生命周期(秒)。动画将在此时间后自动销毁。如果省略,默认为3秒。 |
fps | N/A | 浮点数 | 3.0f | 可选。精灵动画或DrawNode动画的帧率(每秒更新次数)。如果省略,默认为3帧/秒。文本动画通常不使用此参数。 |
AnimationContentType (枚举)
定义临时动画的内容类型,这会影响您需要提供哪些具体内容字段。
Text: 动画内容为文本字符串。此时需要提供textContent字段。Sprite: 动画内容为一系列精灵,用于播放帧动画。此时需要提供spriteNames字段。DrawNode: 动画内容为DrawNodeDef定义,用于更复杂的图像或粒子效果。此时需要提供drawNodeDefName字段。
示例
以下是 EventDef 的示例,展示了 Event_TemporaryAnimationWorkClass 的不同用法:
<Define>
<!-- 假设已有DrawNode_ExplosionEffect, Sprite_Coin1, Sprite_Coin2, Sprite_Coin3 等资源 -->
<!-- 示例1: 在怪物死亡位置生成一个“命中”文本动画 (相对于触发者) -->
<EventDef>
<defName>SpawnHitTextOnDeath</defName>
<label>显示命中文本</label>
<description>在怪物死亡时显示“命中”文本。</description>
<workClass>Event_TemporaryAnimationWorkClass</workClass>
<parameter>
{
"contentType": "Text",
"textContent": "命中!",
"relativeOffset": {"x": 0.5, "y": 1.0, "z": 0.0},
"lifeTime": 1.5,
"isUIAnimation": false
}
</parameter>
</EventDef>
<!-- 示例2: 在特定坐标播放一个金币收集的UI动画 (精灵序列) -->
<EventDef>
<defName>SpawnCoinCollectAnimation</defName>
<label>金币收集动画</label>
<description>在屏幕固定位置播放金币收集UI动画。</description>
<workClass>Event_TemporaryAnimationWorkClass</workClass>
<parameter>
{
"contentType": "Sprite",
"isUIAnimation": true,
"spriteNames": ["Sprite_Coin1", "Sprite_Coin2", "Sprite_Coin3"],
"position": {"x": 100.0, "y": 200.0, "z": 0.0},
"lifeTime": 1.0,
"fps": 10.0
}
</parameter>
</EventDef>
<!-- 示例3: 在敌人身上播放爆炸DrawNode动画,并将其设为敌人子对象 -->
<EventDef>
<defName>SpawnExplosionEffect</defName>
<label>爆炸特效</label>
<description>在敌人头上播放爆炸DrawNode动画。</description>
<workClass>Event_TemporaryAnimationWorkClass</workClass>
<parameter>
{
"contentType": "DrawNode",
"drawNodeDefName": "DrawNode_ExplosionEffect",
"relativeOffset": {"x": 0.0, "y": 0.5, "z": 0.0},
"parentToInitiator": true,
"lifeTime": 0.8,
"fps": 15.0
}
</parameter>
</EventDef>
<!-- 示例4: 在地图随机位置显示一个“提示”文本,无触发者 -->
<EventDef>
<defName>ShowRandomHint</defName>
<label>随机提示</label>
<description>在地图随机位置显示一个提示文本。</description>
<workClass>Event_TemporaryAnimationWorkClass</workClass>
<parameter>
{
"contentType": "Text",
"textContent": "小心前方!",
"position": {"x": 20.0, "y": 80.0, "z": 0.0},
"lifeTime": 2.0
}
</parameter>
</EventDef>
</Define>
复杂参数说明
parameter 字段 (JSON配置)
- 说明:
EventDef中的parameter字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了TemporaryAnimationData的所有配置参数,用于指导Event_TemporaryAnimationWorkClass的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合TemporaryAnimationData的结构。 - JSON属性与C#映射关系:
- 所有JSON属性名(如
contentType,isUIAnimation等)与C#内部数据类TemporaryAnimationData中的对应属性名一致(JSON通常使用驼峰式命名)。
- 所有JSON属性名(如
Vector3的JSON表示: 在JSON中,Vector3类型的字段需要以一个包含x,y,z三个浮点数字段的JSON对象形式表示。- 例如:
"position": { "x": 50.0, "y": 30.0, "z": 0.0 }
- 例如:
- 字符串数组的JSON表示:
spriteNames字段是一个字符串数组,应以JSON数组的形式表示。- 例如:
"spriteNames": ["Sprite_Frame1", "Sprite_Frame2", "Sprite_Frame3"]
- 例如:
- 枚举值的JSON表示:
在JSON中,所有枚举类型(如
contentType)都应以其字符串名称来表示。- 例如:
"contentType": "Sprite"
- 例如:
contentType 字段及其相关内容字段
contentType 字段是动画的核心配置,它决定了动画将显示何种内容。根据您选择的 contentType,以下字段中的且仅其中的一个是必需的,其余字段将被忽略:
- 当
contentType为Text时:textContent(字符串):必须提供动画要显示的文本内容。- 例如:
"contentType": "Text", "textContent": "伤害!"
- 当
contentType为Sprite时:spriteNames(字符串数组) :必须提供组成帧动画的单个精灵名称列表。这些名称必须是游戏资源管理系统可识别的有效精灵名称。动画将按列表顺序循环播放这些精灵。- 例如:
"contentType": "Sprite", "spriteNames": ["FX_Dust1", "FX_Dust2"]
- 当
contentType为DrawNode时:drawNodeDefName(字符串):必须提供DrawNodeDef的defName。DrawNodeDef是一种更复杂的图形定义,可以用于创建包含多个图层、动态效果或粒子系统的动画。- 例如:
"contentType": "DrawNode", "drawNodeDefName": "DrawNode_HealEffect"
位置 (position, relativeOffset) 与父级 (parentToInitiator) 逻辑
动画的生成位置和父级关系遵循以下优先级和逻辑:
- 绝对位置 (
position):如果position字段被设定,则动画将精确地生成在该世界坐标。这是定位的最高优先级。 - 相对偏移 (
relativeOffset):如果position未设置,但relativeOffset字段被设定,并且事件有一个initiator(触发者实体),则动画将生成在initiator的位置加上relativeOffset。 - 触发者位置:如果
position和relativeOffset都未设置,但事件有一个initiator,则动画将生成在initiator的当前位置。 - 默认位置:如果上述所有条件均不满足(即未提供
position,没有relativeOffset或没有initiator),动画将默认生成在世界坐标(0,0,0)处,并会输出警告日志。 - 父级设置 (
parentToInitiator):如果parentToInitiator设置为true并且事件有一个initiator,则生成的动画对象将会被设置为initiator的子对象,这意味着动画会随initiator移动。如果initiator不存在,即使设置为true,动画也不会有父级,并会输出警告。
AI行为树叶节点:攻击目标 (JobNode_AttackTarget)
功能说明
JobNode_AttackTarget 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 寻找到其视野范围内最近的一个敌对目标,并对其发起一次攻击。如果未能找到有效的敌对目标,或者在攻击前目标失效(例如已死亡),则该节点会返回失败。此节点通常用于定义需要主动攻击敌人的行为逻辑链中。
该节点无需任何自定义参数,其行为完全基于 SelfEntity 的当前状态、其与环境中其他实体的关系以及攻击能力。
可用参数
无需配置参数。JobNode_AttackTarget 节点无需任何额外配置即可工作。它的逻辑是自动寻找并攻击 SelfEntity (当前执行行为树的实体)最近的敌对目标。
行为树节点状态 (Status) 返回值
JobNode_AttackTarget 节点执行完毕后,会返回以下状态:
- 成功 (
Success):- 成功在当前区域找到一个有效的敌对实体。
SelfEntity成功地对该敌对实体发起了一次攻击尝试。
- 失败 (
Failure):- 在当前维度中未找到任何有效的敌对实体。
- 找到了敌对实体,但在尝试攻击前该实体变得无效(例如,它已死亡或离开区域)。
SelfEntity由于其他原因无法发起攻击(例如,攻击冷却中、没有武器或攻击能力等)。
示例
以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_AttackTarget 如何在一个基本的怪物行为中被使用:
<Define>
<BehaviorTreeDef>
<defName>BasicMonsterBehavior</defName>
<label>基础怪物行为</label>
<description>怪物寻路并攻击最近的敌人,或者徘徊和空闲。</description>
<!-- 根节点下的行为逻辑 -->
<!-- 条件分支:如果怪物有武器,则尝试攻击 -->
<Node className="ThinkNode_Conditional" value="HasWeapon()">
<!-- 序列节点:先移动到攻击范围,再执行攻击 -->
<childTree>
<li>
<className>ThinkNode_Sequence</className>
<childTree>
<li>
<!-- 移动到攻击范围,如果距离太远就移动,否则直接成功 -->
<className>JobNode_MoveToAttackRange</className>
</li>
<li>
<!-- 攻击最近的敌对目标 -->
<className>JobNode_AttackTarget</className>
</li>
</childTree>
</li>
</childTree>
</Node>
<!-- 默认行为:如果上述攻击条件不满足,则徘徊和空闲 -->
<Node className="ThinkNode_Sequence">
<childTree>
<li>
<!-- 随机徘徊一段时间 -->
<className>JobNode_Wander</className>
</li>
<li>
<!-- 空闲一段时间 -->
<className>JobNode_Idle</className>
</li>
</childTree>
</Node>
</BehaviorTreeDef>
</Define>
在上述示例中,JobNode_AttackTarget 被放置在一个序列节点中。这意味着它只会在 JobNode_MoveToAttackRange 成功执行(即实体已到达攻击范围或无需移动)之后才会尝试执行。整个攻击序列又被包含在一个条件节点 ThinkNode_Conditional 中,确保只有当怪物拥有武器时才会执行攻击行为。
AI行为树叶节点:空闲 (JobNode_Idle)
功能说明
JobNode_Idle 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 进入一段时间的空闲状态。在此期间,实体不会执行任何特定的动作,而是保持“待命”状态,直到预设的空闲时间结束。此节点通常用于填充行为链中需要实体暂停或等待的间隙,例如在完成一个任务后等待下一个指示,或者单纯地在没有其他紧急任务时进行放松。
JobNode_Idle 节点可以通过一个可选的参数来指定空闲的持续时间(以游戏帧为单位)。如果未指定,它将使用基类默认的空闲时间。
可用参数
JobNode_Idle 节点允许通过 BehaviorTreeDef 中 Node 元素的 value 属性来配置其空闲持续时间。
| 参数名 | XML参数名 (value 属性) | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
TimeoutFrames | value | 整数 | 180 | 可选。指定实体将保持空闲状态的帧数。180帧大约对应3秒的游戏时间(假设60帧/秒)。如果未指定此参数,则默认使用基类设定的 180 帧。 |
行为树节点状态 (Status) 返回值
JobNode_Idle 节点执行完毕后,会返回以下状态:
- 运行中 (
Running):- 空闲时间尚未结束。实体将继续保持空闲状态,并在下一个行为树tick时再次执行此节点。
- 成功 (
Success):- 预设的空闲时间已全部耗尽。实体已完成空闲任务,可以继续执行行为树中的下一个节点。
示例
以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_Idle 如何在一个怪物行为中被使用:
<Define>
<BehaviorTreeDef>
<defName>MonsterPatrolBehavior</defName>
<label>怪物巡逻行为</label>
<description>怪物在巡逻和空闲之间切换。</description>
<!-- 序列节点:先移动到巡逻点,然后空闲 -->
<Node className="ThinkNode_Sequence">
<childTree>
<li>
<!-- 移动到一个预定义的巡逻点 -->
<className>JobNode_MoveToPatrolPoint</className>
<!-- 假设此处 JobNode_MoveToPatrolPoint 也有自己的value或子节点配置 -->
</li>
<li>
<!-- 空闲150帧 (2.5秒) -->
<className>JobNode_Idle</className>
<value>150</value>
</li>
</childTree>
</Node>
<!-- 另外一个序列节点,展示不指定value的Idle -->
<Node className="ThinkNode_Sequence">
<childTree>
<li>
<!-- 执行某个任务 -->
<className>JobNode_PerformTask</className>
</li>
<li>
<!-- 空闲默认的180帧 (3秒) -->
<className>JobNode_Idle</className>
</li>
</childTree>
</Node>
</BehaviorTreeDef>
</Define>
在上述示例中:
- 第一个
JobNode_Idle通过value属性指定了 150 帧的空闲时间。 - 第二个
JobNode_Idle没有指定value属性,因此它将使用基类默认的 180 帧空闲时间。
复杂参数说明
value 属性 (空闲帧数)
- 说明:在
BehaviorTreeDef的Node元素中,JobNode_Idle节点的value属性用于直接指定空闲的帧数。它应该是一个可以被解析为整数的字符串。 - 用法:
<className>JobNode_Idle</className><value>300</value>:表示实体将空闲 300 帧(约 5 秒)。<className>JobNode_Idle</className>:表示实体将空闲默认的 180 帧(约 3 秒)。
- 注意事项:
value属性预期接收一个纯数字字符串。如果字符串无法解析为整数,JobNode_Idle将退回到使用默认的空闲帧数。
AI行为树叶节点:移动到攻击范围 (JobNode_MoveToAttackRange)
功能说明
JobNode_MoveToAttackRange 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 寻找其视野范围内最近的敌对目标,然后计算一个合适的移动位置,使其自身能够进入该敌对目标的攻击距离边缘。此节点的目的是确保 SelfEntity 能够移动到可以成功攻击敌人的位置,而不会过于接近或远离。它还包含路径设置、持续移动管理以及卡住检测的逻辑,以应对复杂的寻路情况。
该节点无需任何自定义参数,其行为完全基于 SelfEntity 的当前状态、其与环境中其他实体的关系、攻击范围 (SelfEntity.AttributesNow.attackRange) 以及寻路能力。
可用参数
无需配置参数。JobNode_MoveToAttackRange 节点无需任何额外配置即可工作。它的逻辑是自动寻找最近的敌对目标,并计算确保 SelfEntity 能够到达其攻击范围内的最佳位置。
行为树节点状态 (Status) 返回值
JobNode_MoveToAttackRange 节点执行完毕后,会返回以下状态:
- 运行中 (
Running):- 节点已找到目标并设置了路径,
SelfEntity正在向目标攻击范围移动。 SelfEntity因卡住而被节点检测到,正在重新规划路径。
- 节点已找到目标并设置了路径,
- 成功 (
Success):SelfEntity已经成功移动到其最近敌对目标的攻击范围边缘。
- 失败 (
Failure):- 在当前维度中未找到任何有效的敌对实体。
- 找到了敌对实体,但在尝试设置路径或移动过程中该实体变得无效(例如,它已死亡或离开区域)。
示例
以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_MoveToAttackRange 如何在一个基本的怪物行为中与 JobNode_AttackTarget 节点配合使用:
<Define>
<BehaviorTreeDef>
<defName>MonsterAggressiveBehavior</defName>
<label>怪物侵略性行为</label>
<description>怪物主动移动到攻击范围并攻击。</description>
<!-- 条件分支:如果怪物有武器,则尝试攻击 -->
<Node className="ThinkNode_Conditional" value="HasWeapon()">
<childTree>
<li>
<!-- 序列节点:先移动到攻击范围,再执行攻击 -->
<className>ThinkNode_Sequence</className>
<childTree>
<li>
<!-- 移动到攻击范围边缘,此节点会持续运行直到成功或失败 -->
<className>JobNode_MoveToAttackRange</className>
</li>
<li>
<!-- 成功进入攻击范围后,攻击目标一次 -->
<className>JobNode_AttackTarget</className>
</li>
</childTree>
</li>
</childTree>
</Node>
<!-- 如果没有武器,或者攻击行为失败,则执行默认的徘徊空闲行为 -->
<Node className="ThinkNode_Sequence">
<childTree>
<li>
<!-- 随机徘徊 -->
<className>JobNode_Wander</className>
</li>
<li>
<!-- 空闲一段时间 -->
<className>JobNode_Idle</className>
</li>
</childTree>
</Node>
</BehaviorTreeDef>
</Define>
在上述示例中,JobNode_MoveToAttackRange 被放置在一个序列节点中,位于 JobNode_AttackTarget 之前。这意味着只有当实体成功移动到攻击范围后,JobNode_AttackTarget 才会被执行。这种组合确保了实体在能够有效攻击敌人之前,会先尝试达到最佳的战斗位置,并且能够智能处理寻路过程中的卡住情况。
AI行为树叶节点:徘徊 (JobNode_Wander)
功能说明
JobNode_Wander 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 在其当前位置附近随机选择一个可达的目标点,并移动到该点。一旦到达目标点,该节点即告成功。此节点也包含了卡住检测机制,如果实体在徘徊过程中长时间未移动,则判定为卡住并返回失败,以便行为树可以尝试其他行为。
此节点常用于实现实体的默认空闲行为,如生物在地图上漫无目的地行走,或NPC在没有特定任务时在区域内巡逻。
可用参数
无需配置参数。JobNode_Wander 节点不接受任何来自XML的额外配置。其所有行为(例如徘徊的最大范围、最小移动距离、寻找目标点的尝试次数、卡住检测的阈值和帧数等)均由节点内部的默认逻辑和常量控制。
行为树节点状态 (Status) 返回值
JobNode_Wander 节点执行完毕后,会返回以下状态:
- 运行中 (
Running):- 节点已成功找到一个徘徊目标点,并且
SelfEntity正在向该目标点移动。 SelfEntity尚未到达目标点,但仍在尝试移动。
- 节点已成功找到一个徘徊目标点,并且
- 成功 (
Success):SelfEntity已经成功到达其当前徘徊的目标点。
- 失败 (
Failure):- 在经过多次尝试后,未能找到一个有效且可达的随机徘徊目标点。这通常发生在实体被困在一个无法移动的区域时。
SelfEntity在向目标点移动的过程中被检测到卡住(长时间未移动)。
示例
以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_Wander 如何在一个行为链中被使用:
<Define>
<BehaviorTreeDef>
<defName>PassiveAnimalBehavior</defName>
<label>被动动物行为</label>
<description>动物在没有威胁时,会随机徘徊并短暂空闲。</description>
<!-- 序列节点:先徘徊,然后空闲 -->
<Node className="ThinkNode_Sequence">
<childTree>
<li>
<!-- 随机徘徊到附近一个点 -->
<className>JobNode_Wander</className>
</li>
<li>
<!-- 徘徊结束后,空闲120帧 (约2秒) -->
<className>JobNode_Idle</className>
<value>120</value>
</li>
</childTree>
</Node>
</BehaviorTreeDef>
<BehaviorTreeDef>
<defName>MonsterDefaultPatrol</defName>
<label>怪物默认巡逻</label>
<description>怪物在没有敌人时,会进行随机巡逻。</description>
<!-- 条件节点:如果没有敌人,则执行巡逻 -->
<Node className="ThinkNode_Conditional" value="!HasHostileTarget()">
<childTree>
<li>
<!-- 随机徘徊 -->
<className>JobNode_Wander</className>
</li>
</childTree>
</Node>
<!-- 如果有敌人,则可能执行攻击行为(由其他节点定义) -->
</BehaviorTreeDef>
</Define>
在上述示例中:
- 第一个
BehaviorTreeDef演示了一个被动动物的行为,它会先通过JobNode_Wander移动到附近一个点,然后通过JobNode_Idle暂停一段预设的时间。 - 第二个
BehaviorTreeDef展示了JobNode_Wander如何在ThinkNode_Conditional内部作为默认的巡逻行为,只有在没有敌对目标时才会触发。
复杂参数说明
由于 JobNode_Wander 节点没有任何可直接通过 XML 配置的参数,因此本节不适用。其内部行为逻辑(如徘徊范围、卡住检测等)均已预设。