SuperAPI AI 工具集

pixi-vn-ink-characters

编程与开发

查看项目

更新于 11-06 16:21

技能介绍

用途

该技能用于在 ink 叙事脚本中引用 Pixi'VN 已注册的角色。适用场景包括:让某行 ink 台词归属到某个已注册角色、在文本中内联打印角色显示名、使用带情绪的角色变体,以及在剧情内部修改角色名(命名场景、昵称揭晓等)。前提是角色已通过 CharacterBaseModel 定义,并用 RegisteredCharacters.add(...) 注册;本技能只覆盖从 .ink 文件引用这些角色的部分。

主要能力

1. 将台词归属到角色

格式为 <character_id>: <text>,例如:

mc: Hello, I'm Liam.

Pixi'VN 会按行中第一个 ": "(冒号加空格)分割,检查其前 token 是否为已知角色 id。已知 id 的来源有两种:显式传给 importInkText(text, { characters: [...] }) 或 vitePluginInk({ characters: [...] }) 的 id;或在转换时已存在于 RegisteredCharacters 中的 id(常见情况)。若 token 不匹配任何已知角色,整行会作为普通旁白保留(包括冒号),因此拼错的角色 id 不会报错,而会静默变成乱码式旁白。分割要求字面 ": ",所以 mc:Hello(无空格)不会被识别为台词归属。

注册示例:

import { CharacterBaseModel, RegisteredCharacters } from "@drincs/pixi-vn";

export const mc = new CharacterBaseModel("mc", { name: "Liam" });
RegisteredCharacters.add(mc);

如果角色在 ink 导入/构建步骤之后才注册(Vite 插件下常见,因为 vitePluginInk 的 JSON 导出与内容文件执行时机独立),应通过 vitePluginInk({ characters: [...] }) 或 importInkText(text, { characters: [...] }) 显式传入这些 id,确保分割时能识别。

2. 内联打印角色名:[characterId]

Hello, [mc].

这不是 ink 原生的 {variable} 插值,而是 Pixi'VN 的文本替换机制(方括号 [key]),此处用于把角色 id 替换为角色当前名称。它需要注册一个文本替换处理器,使用内置的 "characterId" 校验模式;官方模板默认自带此配置:

import { TextReplaces } from "@drincs/pixi-vn-ink";
import { RegisteredCharacters } from "@drincs/pixi-vn/characters";

TextReplaces.add((key) => RegisteredCharacters.get(key)?.name, {
  name: "character name",
  validation: "characterId",
  type: "after-translation",
  i18nInterpolation: true,
  description: "Replaces a character ID with the character's name in the game.",
});

validation: "characterId" 表示该处理器只对当前是已注册角色 id 的 key 生效(对照 RegisteredCharacters 检查),无需正则。由于角色名可在运行时改变(见下文重命名),[mc] 始终反映当前名称,而非写剧情时的名称。

3. 角色情绪:id@emotion

mc@happy: Hi, I'm Liam. I'm very happy today.

整个 mc@happy token 会像普通 id 一样对照 RegisteredCharacters 检查;它能解析,是因为 Pixi'VN 角色可用复合 { id, emotion } 键注册(内部以 id@emotion 寻址):

import { CharacterBaseModel, RegisteredCharacters } from "@drincs/pixi-vn";

export const mc = new CharacterBaseModel("mc", { name: "Liam" });
export const mcHappy = new CharacterBaseModel({ id: "mc", emotion: "happy" }, { name: "Liam happy" });

RegisteredCharacters.add([mc, mcHappy]);

情绪变体是一次完整的、独立的 CharacterBaseModel 注册,通常带自己的名称覆盖(此处相同)以及项目渲染层所依赖的精灵/立绘数据(参见 pixi-vn-ink-canvas,用于在台词旁显示情绪专用精灵)。若未注册该变体而引用 mc@sad,行为等同未知 id:该行回退为普通旁白文本。

4. 从 ink 中重命名角色:# rename

示例剧情:

=== start ===
mc: Hello, I'm [mc].
# request input string
mc: My name is:
# rename mc {_input_value_}
mc: My name is [mc]
-> DONE

rename <characterId> <newName> 并非内置标签命令,每个官方模板自行注册,因为“重命名触及哪些字段”因项目而异:

import { characterIdsEnum } from "@/pixi-vn.keys.gen"; // generated by vitePluginPixivn's typeFilePath
import { HashtagCommands } from "@drincs/pixi-vn-ink";
import { RegisteredCharacters } from "@drincs/pixi-vn/characters";
import zod from "zod";

HashtagCommands.add(
  async (script) => {
    const character = RegisteredCharacters.get(script[1]);
    if (character) character.name = script[2];
    return true;
  },
  {
    name: "character rename",
    description: "Renames a character in the game.\n\n```ink\n# rename <characterId> <newName>\n```",
    validation: zod.tuple([zod.literal("rename"), zod.enum(characterIdsEnum), zod.string()]),
  },
);

以普通 add 处理器注册(它直接修改游戏状态,而非返回 PixiVNJsonOperation);关于 add 与 addMapper 的选择,参见 pixi-vn-ink-hashtag-commands。

适用场景

  • 在 ink 对话中为某行台词指定说话角色。
  • 对话里动态显示角色当前名字。
  • 为台词切换带情绪的角色立绘或变体。
  • 在剧情中通过玩家输入改变角色名。

限制与注意

  • 角色必须先定义并注册;本技能不涉及角色定义本身。
  • 角色 id 拼写错误不会报错,而是静默退化为旁白文本。
  • 台词归属必须使用 ": "(冒号加空格),不可省略空格。
  • 若渲染/构建顺序导致角色注册晚于 ink 转换,需通过 characters 选项显式传入 id。
  • 情绪变体需单独完整注册,否则回退为旁白。
  • rename 非内置命令,需项目自行注册。

相关资料

  • pixi-vn-ink-text-replacement:[key] 通用替换机制,[characterId] 建立于其上。
  • pixi-vn-ink-hashtag-commands:# rename 及其他自定义命令的注册方式。
  • pixi-vn-ink:knots 作标签、存储映射、安装。
  • 官方文档:pixi-vn.com/ink/character;pixi-vn.com/start/character(在 JS/TS 中定义 CharacterBaseModel)。