主题
GameData 公式字段赋值位置
需要在图形化编辑器中编写公式时,可在函数字段选择或新建触发器函数;JSON 保存函数引用,不保存 C# lambda。常量、函数引用和纯代码路线,以及未知 JSON 辅助字段与生成失败的区别,见从配置到运行证据。
本文说明纯代码定义 GameData 时,公式字段应该写在双端共享代码里,还是放进 #if SERVER / #if CLIENT。
数据编辑器和触发编辑器会自动处理大多数场景;这条规则主要面向手写 C# GameData 的开发者和 AI 助手。
默认决策
按下面顺序判断:
- 先看字段是否存在于当前端 API。只存在于
docs/api/server/的字段必须在#if SERVER中赋值;只存在于docs/api/client/的字段必须在#if CLIENT中赋值。 - 再看公式偏向。
[DataEditor(FunctionBias = FunctionBias.Server)]表示服务端公式偏向,不表示字段本身一定是服务端专属。这类字段默认推荐只在#if SERVER中赋值。FunctionBias.Client同理默认放在#if CLIENT。 - 最后看客户端是否需要读这个值。如果客户端 UI、预览或表现确实要读取同一个公式字段,并且公式只使用双端共有 API 或常量,可以写成双端共享公式。
- 不要把所有 GameData 都无脑包进
#if SERVER。表现、Actor、UI、单位显示数据、客户端可见的技能展示数据仍然需要客户端定义。
优先查 docs/api/client/ 和 docs/api/server/ 中的字段是否存在,并阅读字段 XML 注释。带有服务端公式偏向的字段会直接在 API 注释中说明“默认可只在 #if SERVER 中赋值,但字段不因此变成服务端专属”。Schema 中的 x-platform-availability / x-function-bias 只是机器可读补充,不是理解这条规则的必读入口。
服务端专属字段
如果字段只在服务端 API 中出现,就必须放进 #if SERVER。例如 AI 思维树运行时对象 AIThinkTree 只存在于服务端,因此参数包含 AIThinkTree 的公式通常都是服务端专属。
csharp
_ = new GameDataAINodeValidateScan(MyLinks.ScanTarget)
{
IgnoreLeash = true,
#if SERVER
Range = static thinkTree => thinkTree.ScanRange + 200,
#endif
};GameDataAINodeValidateScan.Range 在客户端 API 中不存在;不加 #if SERVER 会导致客户端编译失败。
服务端公式偏向字段
很多 GameDataEffectXXX 节点的字段在双端 API 中都存在,但效果树实际只在服务端执行。带有 [DataEditor(FunctionBias = FunctionBias.Server)] 的公式字段默认可以只在服务端赋值。
csharp
_ = new GameDataEffectUnitModifyLevel(MyLinks.ModifyLevel)
{
Operation = PropertyModificationOperation.Add,
#if SERVER
Amount = static ctx =>
Math.Max(1, (int)((ctx.Caster.GetUnitPropertyFinal(GSC.GameDataUnitProperty.AttackDamage) ?? 100) / 100)),
#endif
};客户端仍然能看到这个字段的默认值或数据结构,但不会运行服务端效果逻辑。把复杂效果公式放在 #if SERVER 中,可以直接使用服务端 API,避免为了双端兼容而牺牲表达力。
双端共享公式
如果字段会被客户端读取来显示 UI、预览技能数据或做表现,并且公式只依赖常量或双端共有 API,可以写成共享公式。
csharp
_ = new GameDataAbilityExecute(MyLinks.Fireball)
{
DisplayName = "火球",
Range = static (_) => 500,
};技能施法距离是典型例子:核心判定通常在服务端,但客户端可能读取同一字段显示技能说明或范围提示。此时共享常量或共享 API 公式是合理的。
AI 助手规则
生成或修改 GameData 代码时,AI 应优先使用下面的简化规则:
- 字段只在一端 API 中存在:只在对应
#if中赋值。 FunctionBias.Server:默认只在#if SERVER中赋值,除非客户端明确需要读这个字段且公式双端兼容。FunctionBias.Client:默认只在#if CLIENT中赋值。- 常量公式和双端共有 API 公式可以共享,但不要为了共享而调用不存在于另一端的 API。
GameDataEffectXXX的效果公式默认按服务端公式处理。