Files
Genarrative/docs/prd/AI_NATIVE_RUNTIME_ITEM_GENERATION_DESIGN.md
高物 c49c64896a
Some checks failed
CI / verify (push) Has been cancelled
初始仓库迁移
2026-04-04 23:57:06 +08:00

13 KiB
Raw Blame History

AI 原生游戏的运行时物品生成设计建议

更新时间:2026-04-02

0. 设计目标

这份方案针对当前项目,回答的是:

如果要把运行时物品生成做成“AI 原生”,应该怎样设计,才能既贴合背景 / NPC / 当前事件,又不会把数值系统做崩。

这里的“AI 原生”不是指“让模型直接胡乱造装备”,而是指:

  • 物品的语义、出处、命名、关系、叙事理由由 AI 根据上下文生成
  • 物品的稀有度、build 标签、数值预算、持久化结果由本地规则编译和裁剪

一句话:

AI 决定这是什么,规则决定它能做什么。

1. 设计原则

1.1 物品必须是“当前故事的一部分”

运行时物品不该只是“随机掉了个稀有剑”。

每个重要物品都至少回答 4 个问题:

  1. 它为什么会出现在这里?
  2. 它和哪个场景背景有关?
  3. 它和哪个 NPC / 势力 / 怪物有关?
  4. 它对当前玩家 build 为什么有意义?

1.2 物品收益以“标签倾向”优先,纯数值为辅

建议把 AI 原生物品的主要收益做成两大类:

  1. 获得 build 标签
    • 永久标签:主要由装备 / 稀有饰品 / 关键遗物提供
    • 限时标签:主要由消耗品 / 临时护符 / 战场符箓提供
  2. 少量直接数值
    • 只做补充,不做主菜
    • 避免数值碾压 build 语义

也就是说,运行时物品的第一身份应该是:

“把玩家的构筑推向某种风格”

而不是:

“给一个更大的攻击数字”

1.3 物品生成必须显式读取上下文

建议运行时物品生成必须至少读取以下上下文:

  • 世界背景
  • 当前场景 / 地标 / 氛围
  • 当前 encounter / 相关 NPC / 相关怪物
  • 最近 1~3 个关键剧情行为
  • 玩家当前装备与激活 build 标签
  • 玩家当前缺口
    • 续航不够
    • 控场不足
    • 缺切后
    • 缺护体
  • 当前奖励渠道
    • 宝藏
    • 交易
    • 委托
    • 掉落
    • 观察所得

1.4 AI 只产出“意图”,本地编译成成品

不要让 AI 直接返回最终 InventoryItem

建议让 AI 先返回的是“物品意图”:

  • 物品主题
  • 物品来源
  • 关联对象
  • 倾向标签
  • 永久 / 限时
  • 用途类型

然后本地再把它编译成:

  • category
  • rarity
  • tags
  • statProfile
  • useProfile
  • buildProfile
  • value

这样才能稳定、可测试、可平衡。

2. 建议的系统结构

建议把新系统拆成 4 层。

2.1 上下文采样层

输入一份统一的 RuntimeItemContext

type RuntimeItemContext = {
  worldType: WorldType | null;
  customWorldProfile?: CustomWorldProfile | null;
  sceneId?: string | null;
  sceneName?: string | null;
  sceneDescription?: string | null;
  landmarkHints?: string[];
  encounter?: Encounter | null;
  relatedNpcState?: NpcPersistentState | null;
  recentStoryMoments: StoryMoment[];
  playerCharacter: Character;
  playerEquipment: EquipmentLoadout;
  activeBuildBuffs: TimedBuildBuff[];
  activeBuildTags: string[];
  generationChannel: "treasure" | "npc_trade" | "npc_reward" | "monster_drop" | "quest_reward" | "discovery";
};

这一层的目标不是做物品,而是把“这次生成到底是在什么局面下发生”说清楚。

2.2 AI 意图层

让模型只生成一个轻量蓝图:

type RuntimeItemIntent = {
  narrativeTheme: string;
  sourceKind: "npc" | "scene" | "monster" | "faction" | "quest" | "ancient";
  sourceName: string;
  reasonToAppear: string;
  itemArchetype: "equipment" | "consumable" | "material" | "relic" | "quest";
  permanence: "permanent" | "timed";
  desiredBuildTags: string[];
  desiredStatBias: Array<"hp" | "mana" | "outgoing" | "mitigation" | "cooldown">;
  relationHooks: string[];
};

重点是:

  • AI 负责“它像什么”
  • 不负责“最终数值是多少”

2.3 本地编译层

本地把 RuntimeItemIntent 编译成正式物品:

  • 先做标签规范化
    • normalizeBuildTags
  • 再判定品类
    • 装备 / 消耗品 / 材料 / 稀有品 / 剧情物
  • 再套预算
    • rarity budget
    • stat budget
    • tag budget
    • duration budget
  • 最后写入:
    • buildProfile
    • statProfile
    • useProfile
    • value

2.4 叙事回写层

物品成品生成后,再把这些信息回写到叙事文本:

  • 它看起来像什么
  • 它为什么来自这个 NPC / 地点
  • 它和哪条线索或关系有关
  • 玩家为什么会觉得“这东西确实该在这里出现”

这一步仍然可以交给 AI但只能读“已经生成好的成品”。

3. 建议的物品类型设计

3.1 永久 build 标签物品

适合:

  • 武器
  • 护甲
  • 饰品
  • 关键遗物

建议规则:

  • 常规装备最多给 1 个核心永久标签
  • 稀有或史诗装备可给 1 个核心标签 + 1 个协同标签
  • 传说物品可以额外充当 set / faction / NPC build 锚点

示例:

  • “渡口缉索短刃”

    • 永久标签:快袭
    • 协同标签:追击
    • 小量数值:outgoingDamageBonus
  • “镇河旧誓铜符”

    • 永久标签:守御
    • 协同标签:护体
    • 小量数值:maxManaBonus

3.2 限时 build 标签物品

适合:

  • 药剂
  • 符箓
  • 临时护符
  • 战场应急工具

建议规则:

  • 只通过 useProfile.buildBuffs 生效
  • 持续 1~3 回合
  • 一次最多提供 1~2 个标签
  • 可叠加刷新时长,但不建议无限堆层

示例:

  • “雾沼息行符”
    • 2 回合获得:风行游击
  • “火工催压油”
    • 1 回合获得:爆发
    • 同时 cooldownReduction: 1

3.3 少量直接数值物品

适合做补充,而不是 build 主轴。

建议预算:

  • 武器:
    • outgoingDamageBonus 小幅增加
  • 护甲:
    • maxHpBonus
    • 或少量 incomingDamageMultiplier
  • 饰品:
    • maxManaBonus
    • 或轻量 outgoingDamageBonus
  • 消耗品:
    • hpRestore
    • manaRestore
    • cooldownReduction

建议约束:

  • 常规运行时随机物品,数值权重应低于标签权重
  • 不要让一个完全无标签的高数值物品压过语义鲜明的 build 物品

4. 如何保证“高度贴合背景和 NPC”

4.1 生成必须绑定三个锚点

建议每个 AI 原生物品至少有三个锚点:

  1. 场景锚点
    • 例如矿道、渡口、祭坛、雾林、裂界前线
  2. 关系锚点
    • 某个 NPC、某个势力、某类怪物、某段旧事
  3. 玩法锚点
    • 玩家当前 build 缺口或当前风险

如果一个候选物品说不清这三个锚点,就不要发。

4.2 命名要使用世界词汇表,不要只按品类随机拼接

建议名字由三部分组成:

来源词 + 关系词 + 品类词

例如:

  • “锁风渡缉索短刃”
  • “药谷回岚灵露”
  • “断碑旧誓护心佩”
  • “裂界巡守压纹符”

来源词来自:

  • 场景 / 地标
  • NPC 身份
  • 势力 / 流派
  • 当前任务线

而不是仅仅:

  • 稀有前缀 + 武器名

4.3 描述文案要回答“为什么现在拿到它”

建议每个重要物品描述都带一句运行时来源理由:

  • 是谁留下的
  • 是从谁身上掉的
  • 为什么这时能交易给你
  • 为什么这次观察能发现它

这样玩家会感觉它是叙事结果,而不是系统掉表。

5. 建议的平衡规则

5.1 稀有度决定预算,不直接决定强度飞跃

建议把稀有度主要用于控制:

  • 可带多少标签
  • 是否允许 set / faction 锚点
  • 叙事权重和经济价值

而不是简单理解为:

  • 稀有度越高,数值就暴涨

建议预算参考:

稀有度 永久标签 限时标签 数值预算
common 0~1 1 很小
uncommon 1 1~2
rare 1+1协同 2 中等偏小
epic 2 或 set 锚点 2 中等
legendary 2 + 关系锚点 2~3 中等,但仍受上限约束

5.2 当前阶段优先支持“补短板”和“定方向”

建议运行时物品生成时,优先做这两类决策:

  1. 补短板
    • 玩家 build 缺续航,就更容易拿到 回复 / 续战 / 护体
    • 玩家 build 缺切后,就更容易拿到 快袭 / 突进 / 风行
  2. 定方向
    • 当玩家已经有明显 build 倾向时,再投放协同物品,把这条路做深

不建议一味“追高强度”,否则玩家会频繁被迫换流派。

5.3 运行时物品要避免频繁彻底改流派

建议把随机物品对 build 的影响控制为:

  • 大多数时候:
    • 强化现有方向
    • 或提供邻近方向
  • 少数特殊奖励:
    • 才允许提供“转流派锚点”

这样玩家会觉得构筑在成长,而不是被系统不断推翻。

6. 建议的接入点

6.1 宝藏奖励

当前最适合先改的是 resolveTreasureReward

建议把它升级为:

  • 先收集:
    • scene preset
    • treasure hint
    • 最近事件
    • 当前遭遇 NPC / 怪物痕迹
  • 再生成 1 个上下文物品
  • 剩余奖励继续走稳定资源:
    • 货币
    • 基础材料
    • 常规补给

这样宝藏会从“奖励池”变成“叙事发现”。

6.2 NPC 交易 / 赠礼 / 帮助

建议给 NPC 增加“关系定制物品”出口:

  • 商人:
    • 卖与你当前 build 有关、但带其身份烙印的物品
  • 帮助奖励:
    • 给限时道具或一次性符箓
  • 高好感 NPC
    • 才会给带永久 build 标签的私人遗物/信物

这样交易和关系系统就会真正联动。

6.3 怪物掉落

建议掉落分两层:

  1. 基础掉落
    • 继续走 preset / material / loot table
  2. 语义掉落
    • 从怪物生态、战斗风格、所在场景生成一个 build 倾向物品或精粹

例如:

  • 重甲守卫掉:
    • 守御精粹
    • 护体甲片
  • 雾林刺客掉:
    • 快袭羽饰
    • 风行药囊

6.4 委托奖励

任务奖励最适合给:

  • 带关系来源的永久物品
  • 剧情关键 rare / relic
  • 能把玩家 build 往下一个阶段推一把的奖励

这类物品最适合绑定:

  • 委托发布人
  • 委托目标
  • 地标
  • 任务线真相

7. 建议新增的数据结构

建议在不推翻现有 InventoryItem 的前提下,新增一层来源元数据。

type RuntimeItemNarrativeBinding = {
  generationChannel: "treasure" | "npc_trade" | "npc_reward" | "monster_drop" | "quest_reward" | "discovery";
  sceneId?: string;
  sceneName?: string;
  relatedNpcId?: string;
  relatedNpcName?: string;
  relatedMonsterId?: string;
  relatedFaction?: string;
  storyReason: string;
  eventHook?: string;
};

type RuntimeItemMetadata = {
  origin: "catalog" | "procedural" | "ai_compiled";
  seedKey?: string;
  narrativeBinding?: RuntimeItemNarrativeBinding;
};

然后在 InventoryItem 上增加可选字段:

interface InventoryItem {
  runtimeMetadata?: RuntimeItemMetadata;
}

这样后面 UI、日志、剧情回放都能解释

这个物品到底从哪来。

8. 推荐的最小落地顺序

建议不要一步把所有入口都改成 AI 原生,而是分三阶段。

阶段 A先做“上下文编译器”不改所有入口

新增:

  • src/data/runtimeItemDirector.ts
  • src/data/runtimeItemCompiler.ts
  • src/types/runtimeItem.ts

先只负责:

  • 接收上下文
  • 生成意图
  • 编译成 InventoryItem

阶段 B先接一个入口验证

优先接:

  • treasureInteractions.ts

因为它最独立,风险最小,最容易观察“贴合背景”的提升。

阶段 C再接 NPC 与任务

等宝藏验证稳定后,再接:

  • NPC 交易
  • NPC 帮助奖励
  • 任务奖励

最后再考虑怪物掉落的 AI 原生语义层。

9. 这套方案和当前仓库为什么契合

这套方案不是另起炉灶,而是直接复用当前仓库已经有的能力:

  • 复用 InventoryItem
  • 复用 ItemStatProfile
  • 复用 ItemUseProfile
  • 复用 ItemBuildProfile
  • 复用 normalizeBuildTags
  • 复用 TimedBuildBuff
  • 复用装备、背包、锻造、build 结算
  • 复用“AI 叙事,本地规则结算”的总边界

所以它不是推翻当前系统,而是补上当前系统最缺的那一层:

上下文感知的运行时物品导演。

10. 最后结论

对这个项目来说,理想的 AI 原生运行时物品生成不应该做成“AI 随机喷装备”,而应该做成:

  1. AI 根据场景、背景、NPC、最近事件和玩家 build先生成物品语义意图。
  2. 本地规则把这个意图编译成带永久或限时 build 标签、并附带少量数值加成的正式物品。
  3. 物品必须能解释“为什么它会在这里,由谁带来,对当前玩家为什么有意义”。
  4. 宝藏、交易、任务、掉落都逐步接入同一套导演层。

这样生成出来的物品才会同时满足三件事:

  • 像故事里长出来的
  • 像 build 里需要的
  • 像系统里可控的