非玩家角色(NPC)是类似村民的实体,可以为其配置带有消息和多个按钮的对话界面。最初设计用于冒险地图,但随着/dialogue命令的引入,现在也可用于常规附加包中。

对话文件 ​NPC对话数据存储在行为包根目录下dialogue文件夹中的对话文件里。以下是一个基础NPC对话文件示例:

dialogue/example.diag.jsonjson{

"format_version": "1.17",

"minecraft:npc_dialogue": {

"scenes": [

{

"scene_tag": "example",

"npc_name": "Steve",

"text": "Hello"

}

]

}

}123456789101112该文件中包含场景数组,每个场景代表独立对话。所有对话可集中在一个文件,也可分散存储。每个场景对象包含以下可配置属性:

scene_tag ​场景标识符,用于定位特定场景。

npc_name ​NPC显示名称(可选)。若未指定,将使用NPC实体默认名称§eNPC。

text ​对话气泡中显示的文本内容(可选)。

on_open_commands ​对话打开时执行的命令数组(可选)。

json"on_open_commands": [

"/say Hello"

]123on_close_commands ​对话关闭时执行的命令数组(可选)。

json"on_close_commands": [

"/say Goodbye"

]123buttons ​对话框中显示的按钮配置数组(可选)。

json"buttons": [

{

"name": "Button One",

"commands": [

"/say Button One Pressed!"

]

},

{

"name": "Button Two",

"commands": [

"/say Button Two Pressed!",

"/say Secondary Command for Button Two"

]

}

]123456789101112131415玩家选择机制 ​在on_open_commands、on_close_commands及按钮命令中,可使用常规选择器(如@p选择最近玩家)。但注意这些选择器以NPC实体为基准执行,多人游戏时可能造成混淆。为此引入特殊选择器@initiator,始终指向当前打开对话的玩家。

json"buttons": [

{

"name": "Levitation Please",

"commands": [

"/effect @initiator levitation"

]

}

]12345678该选择器仅限NPC对话中使用,不可用于其他场景。

多语言支持 ​所有面向用户的对话属性均可实现本地化:

json"npc_name": {

"rawtext": [

{

"translate": "entity.endermite.name"

}

]

}1234567需在资源包语言文件中指定对应翻译键值。例如entity.endermite.name会被翻译为"末影螨"。

打开对话 ​使用/dialogue命令控制对话界面,语法如下: /dialogue open [sceneName:string]

:指向具有minecraft:npc组件的实体选择器(如原版NPC),决定命令执行位置及对话NPC外观。:指向接收对话的玩家选择器。[sceneName:string]:匹配scene_tag的字符串(可选),未指定时将显示该NPC上次使用的对话。示例命令(为最近玩家打开最近NPC的"example"对话):

/dialogue open @e[type=npc,c=1] @p example1修改对话 ​/dialogue change命令可变更NPC对话配置(需玩家手动打开后生效),语法: /dialogue change [player: target]

:目标NPC选择器。:匹配scene_tag的字符串。[player: target]:目标玩家选择器(可选),未指定时影响所有玩家。示例命令(将最近NPC对话改为"example"并随机选择玩家):

/dialogue change @e[type=npc,c=1] example @r1完整示例 ​本示例将创建实现右键传送功能的物品。GitHub源码包含完整实现,需使用本文档顶部的清单文件。

创建NPC实体 ​即使NPC不可见,仍需通过以下命令创建并保持常加载状态:

functions/setup.mcfunctiontickingarea add 0 1 0 0 2 0

summon npc "§r" 0 1 012该函数在坐标(0,0)创建常加载区,并在基岩层生成无名NPC。可通过player.json或tick.json自动执行,或手动运行。

TIP

无需预生成NPC的替代方案:

在玩家行为中添加minecraft:npc组件指定BP/dialogue文件夹中的场景从玩家实体执行命令:/dialogue open @s @s 1优劣分析: ​+ 无需处理NPC隐藏问题+ 免除常加载区维护- 非设计用途可能导致不稳定- 其他玩家点击该玩家也会触发对话可通过添加minecraft:interaction组件避免此问题:

json"minecraft:interact": {

"interactions": [

{

"on_interact": {

"filters": {

"all_of": [

{

"test": "is_family",

"subject": "other",

"value": "player"

}

]

}

}

}

]

}1234567891011121314151617对话文件配置 ​包含两个传送菜单场景的对话文件:

dialogue/example.diag.jsonjson{

"format_version": "1.17",

"minecraft:npc_dialogue": {

"scenes": [

{

"scene_tag": "main_teleport_menu",

"npc_name": "Teleport",

"text": "Where would you like to teleport?",

"buttons": [

{

"name": "Districts",

"commands": [

"/dialogue open @e[type=npc,c=1] @initiator districts_teleport_menu"

]

},

{

"name": "My Base",

"commands": ["/tp @initiator -20 4 -20"]

},

{

"name": "World Spawn",

"commands": ["/tp @initiator 0 4 0"]

}

]

},

{

"scene_tag": "districts_teleport_menu",

"npc_name": "District Teleport",

"text": "What district would you like to teleport to?",

"buttons": [

{

"name": "< Back",

"commands": [

"/dialogue open @e[type=npc,c=1] @initiator main_teleport_menu"

]

},

{

"name": "Shop District",

"commands": ["/tp @initiator 20 4 20"]

},

{

"name": "Gaming District",

"commands": ["/tp @initiator 20 4 -20"]

}

]

}

]

}

}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849创建功能物品 ​使用末影珍珠纹理创建触发对话的自定义物品:

物品JSON ​BP/items/teleport_menu.jsonjson{

"format_version": "1.21.70",

"minecraft:item": {

"description": {

"identifier": "wiki:teleport_menu",

"menu_category": {

"category": "items"

}

},

"components": {

"minecraft:icon": "ender_pearl",

"minecraft:glint": true,

"minecraft:display_name": {

"value": "Teleport Menu"

},

"minecraft:custom_components": ["wiki:teleport_menu"]

}

}

}12345678910111213141516171819自定义组件脚本 ​BP/scripts/teleportMenu.jsjsimport { world } from "@minecraft/server";

const ItemTeleportMenuComponent = {

onUse({ source }) {

source.runCommand("dialogue open @e[type=npc, c=1] @s main_teleport_menu");

},

};

world.beforeEvents.worldInitialize.subscribe(({ itemComponentRegistry }) => {

itemComponentRegistry.registerCustomComponent("wiki:teleport_menu", ItemTeleportMenuComponent);

});1234567891011测试流程 ​打包文件并导入Minecraft创建新超平坦世界(需开启作弊和实验性玩法)执行/function setup初始化NPC通过/give @s wiki:teleport_menu获取物品切换生存模式(创造模式无法触发对话)手持物品右键使用鸣谢 ​本教程基于Minecraft创作者文档相关内容编写。