用途
该技能用于在 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)。