主题
自动挂载模型表现
系统文档:docs/systems/AutoAttachedModelPresentationSystem.md。基础 Actor 概念见 docs/systems/ActorSystem.md;物品槽位和装备生命周期见 docs/systems/ItemSystem.md。
与 GameGraph 下钻接口的表里关系
“附加模型”是被挂到宿主上的外观模型;本 Skill 的“自动挂载模型表现”是通过 Actor 与数据配置自动维护它的上层功能。GameGraph 的 AnimatedModelComponent.AttachAdditionModel(...) 是该功能的下钻版本,复用相同的挂载、骨骼跟随与可选宿主网格裁剪机制;下钻后宿主选择、挂载时机和 AdditionModelAttachment.Detach() 生命周期由调用方管理。ActorAdditionModel 继续属于 Actor 层。
直接 GameGraph 角色、代码控制换装或外观预览,转到 GameGraph 附加模型挂载;上层单位/物品/Buff 自动外观继续走本 Skill。下钻无需 model link 或附加模型 Actor,也不会自动监听物品槽位变化。不要让两条路线重复创建同一外观。
词汇边界
面向外部用户时说“自动挂载模型表现”“附加模型 Actor”“携带/装备后的外观表现”。不要使用底层渲染实现名或项目内分类名。公开字段名可以使用,例如 GameDataActorAdditionModel、ActorArray、CullHostMesh。
选择配置入口
| 用户需求 | 写到哪里 |
|---|---|
| 物品装备或携带后给主人显示模型/光效 | GameDataItemMod.Modifications[ItemSlotType.*].ActorArray |
| 单位出生就自带外观 | GameDataUnit.ActorArray |
| Buff、技能、效果持续期间显示外观 | 对应数据的 ActorArray |
| 直接 GameGraph 角色、换装预览、显式挂载与解除 | GameGraph 下钻 Skill |
| 地上掉落物自身模型 | GameDataItem.Unit 指向的 GameDataUnit |
| 地上掉落物品质光效 | GameDataItemQuality.ActorArray |
| 服务端权威碰撞或命中判定 | 不用表现 Actor;改用 Unit、物理或 replicated Node |
标准物品配方
- 定义
GameDataModel,填资源路径。 - 定义
GameDataActorAdditionModel,通常只填Model;不要填挂接槽位,填写Socket也不会生效。不要把Offset/Rotation/Scale当成此功能的主要对齐方案。 - 把该 Actor link 放进
GameDataItemMod.Modifications[ItemSlotType.Equip].ActorArray或目标槽位。 - 不写客户端手动创建/销毁逻辑;槽位变化时框架自动维护表现。
美术资源前置条件
生成方案前先确认资源是否适合自动挂载模型表现:
- 美术资源应使用目标宿主的原始骨架制作;程序侧不会通过
Socket指定手、背、头等槽位。 - 在宿主 Bind Pose 下把模型放到正确位置。
- 把模型蒙皮到宿主骨骼:刚性手持物通常对手骨或表现用骨骼做 100% 权重;衣服、披风等按身体骨骼正常蒙皮。
- 可以只保留实际使用的骨骼及必要父骨骼;骨骼名称必须和宿主完全一致,避免 DCC 工具自动添加命名空间或改名。
- Bind Pose、坐标轴、单位和骨骼初始变换必须与宿主一致,否则可能漂移、变形,甚至影响宿主蒙皮。
- 导出带 Skin 和骨骼的 FBX,不要导成纯静态模型;通常不需要动画。
- 不同体型、职业或骨架如果摆放不同,优先使用不同模型资源或不同
GameDataActorAdditionModel。 - 需要覆盖宿主主体的大面积外观,才考虑
CullHostMesh = true;普通手持物、背饰、挂件、头饰通常保持false。 - 如果用户反馈位置不对,优先建议检查 Skin、骨骼名、Bind Pose、坐标轴、单位、导出版本和资源适配体型,不要建议填写
Socket,也不要把普通 Actor 偏移当成主方案。
csharp
using GameCore.ActorSystem.Data;
using GameCore.Container;
using GameCore.ItemSystem.Data;
using GameCore.ResourceType.Data;
using GameData;
static readonly GameLink<GameDataModel, GameDataModel> VisualModel =
new("$GameEntry.Models.HandHeldLantern"u8);
static readonly GameLink<GameDataActor, GameDataActorAdditionModel> VisualActor =
new("$GameEntry.Actors.HandHeldLantern"u8);
static readonly GameLink<GameDataItem, GameDataItemMod> Item =
new("$GameEntry.Items.Lantern"u8);
static void RegisterItemVisual()
{
_ = new GameDataModel(VisualModel)
{
Asset = "deco/example/lantern/model.prefab"u8,
};
_ = new GameDataActorAdditionModel(VisualActor)
{
Model = VisualModel,
// 无需填写挂接槽位;填写 Socket 也不会生效。
// 位置、朝向和骨骼跟随由美术资源本身决定。
CullHostMesh = false,
};
_ = new GameDataItemMod(Item)
{
DisplayName = "提灯",
Unit = MyItemUnits.LanternOnGround,
Modifications = new()
{
[ItemSlotType.Equip] = new()
{
ActorArray = [VisualActor],
},
},
StackStart = 1,
StackMax = 1,
};
}CullHostMesh 规则
CullHostMesh 是公开配置字段,含义是“附加模型覆盖宿主主体时,减少宿主网格与附加模型重叠显示”。默认保持 false。
只在这些情况考虑 true:
- 附加模型是外套、披风、整套外观或覆盖身体大面积区域的模型。
- 宿主模型和附加模型发生明显穿插或重叠闪烁。
不要为了普通手持物、背饰、头饰、挂件默认开启。开启后必须实际预览,因为它影响的是宿主显示效果,不是碰撞、判定或服务端逻辑。
生成代码时的注意事项
以下规则适用于 Actor 上层;GameGraph 下钻接口使用具体组件与 Prefab 资源,不套用 ActorArray / actor link 配方。两条路线共用美术资源适配要求。
GameDataActorAdditionModel与引用它的物品/单位数据应在双端可见的数编初始化里注册;不要只放进#if SERVER。ActorArray存 actor link,不存 model link。- 不要填
Socket。自动挂载模型表现无需填写挂接槽位,填写也不会生效;不要生成依赖Socket的方案。 - 不要把
Offset/Rotation/Scale当成自动挂载模型的主要对齐方案;位置问题优先回到美术资源检查。 - 装备外观跟随物品槽位生命周期;不要额外写客户端常驻列表去重复创建同一个模型。
- 表现 Actor 不做玩法判定。需要命中、碰撞、拾取范围或服务端权威位置时,另建逻辑对象或物理节点。
排错速查
| 症状 | 优先检查 |
|---|---|
| 装备后没显示 | 当前槽位是否有 ActorArray;物品需求是否满足;客户端是否能解析 actor/model link |
| 地上能看到,装备后看不到 | 地上表现配在 GameDataItem.Unit,但装备表现漏配 Modifications[slot].ActorArray |
| 装备能看到,地上看不到 | 装备表现和地面物品表现是两条配置;检查 GameDataItem.Unit |
| 位置不对 | Skin、骨骼名、Bind Pose、坐标轴、单位、导出版本;不要依赖 Socket 或普通 Actor 偏移 |
| 不同角色位置差异很大 | 资源只适配一种体型/骨架;拆不同模型资源或不同 Actor 配置 |
| 主体穿插 | 只对覆盖主体的大面积附加模型尝试 CullHostMesh = true |