Skip to content

节点(Nodes):故事的骨架

在互动故事中,节点 (Node) 是构成故事的基本单位。您可以将每个节点想象成故事中的一个场景、一个段落、一个事件,甚至是玩家做出选择后的一个结果。所有这些节点共同构成了故事的完整流程。在 common/data.json 中,所有的节点都定义在 "nodes" 对象内部。

3.1 nodes 对象的结构

"nodes" 对象是一个键值对的集合,其中每个键(Key)都是一个唯一的节点ID,而每个值(Value)则是一个描述该节点属性的对象。节点ID是您在故事中引用该节点的唯一标识符,因此它必须是独一无二的。

json
{
  "nodes": {
    "node_id_1": {
      "text": "这是第一个节点的内容。"
    },
    "node_id_2": {
      "text": "这是第二个节点的内容。"
    }
  }
}

3.2 节点的基本属性

每个节点对象都可以包含以下核心属性:

  • "title" (可选,字符串):节点的标题。这个标题会显示在顶栏,帮助玩家了解当前所处的场景或事件。

  • "text" (必填,字符串):节点的主要文本内容。这是故事叙述的核心部分。

至关重要的是,所有交互元素,如链接,都必须通过特殊的文本标记(如 {0}, {1})嵌入到 "text" 中才能显示。

  • "links" (可选,数组):一个包含链接对象的数组。每个链接对象代表一个玩家可以选择的选项。

  • "actions" (可选,数组):一个包含动作对象的数组。这些动作会在玩家进入该节点时自动执行,用于改变游戏状态、触发事件等。

以下是一个包含这些基本属性的节点示例:

json
"start_node": {
  "title": "宁静的早晨",
  "text": "你从睡梦中醒来,阳光透过窗帘洒在你的脸上。这是一个新的开始。\n\n你决定 {0} 还是 {1}?",
  "links": [
    { "text": "起床", "target": "wake_up_scene" },
    { "text": "再睡一会儿", "target": "sleep_more_scene" }
  ],
  "actions": [
    { "type": "set", "target": "var.player.energy", "value": 100 },
    { "type": "toast", "message": "新的一天开始了!" }
  ]
}

"links" 属性定义了玩家从当前节点可以做出的选择。每个链接都是一个对象,至少包含 "text""target" 两个属性:

  • "text" (必填,字符串):显示给玩家的选项文本。
  • "target" (必填,字符串):当玩家选择此链接时,故事将跳转到的目标节点的ID。

除了 "text""target",链接还可以包含以下可选属性:

  • "condition" (可选,字符串):一个条件表达式。如果提供了 "condition",则只有当该条件满足时,此链接才可以被点击(否则会变灰)。
  • "actions" (可选,数组):一个包含动作对象的数组。这些动作会在玩家点击此链接时,且在跳转到 "target" 节点之前执行。
  • "variants" (可选,数组):一个包含变体链接的数组。它允许同一个链接根据不同的条件,显示不同的文本、跳转到不同的目标或执行不同的动作。
  • "random" (可选,数组):一个包含随机选项的数组。如果一个链接包含 "random" 属性,点击它会随机决定跳转的目标和执行的动作。

以下是包含可选属性的链接示例:

json
"links": [
    { "text": "向东走", "target": "forest_east" },
    { 
        "text": "打开宝箱", 
        "target": "treasure_chest_open", 
        "condition": "var.player.hasKey" 
    },
    { 
        "text": "捡起地上的金币", 
        "target": "path_continue", 
        "actions": [{ "type": "add", "target": "var.player.gold", "value": 10 }] 
    }
]

再次强调: 无论您定义了多少链接,都必须在节点的 "text" 属性中使用 {0}, {1}, {2}... 这样的标记,才能让它们在屏幕上显示出来。

3.4 节点ID的命名规范

虽然节点ID可以是任何唯一的字符串,但遵循一致的命名规范将极大地提高 data.json 的可读性和可维护性。建议采用以下策略:

  • 描述性:ID应该能够简要地描述节点的内容或功能,例如 forest_path_crossroads
  • 小写和下划线:使用小写字母,并用下划线 _ 分隔单词,例如 chapter_1_start

3.5 节点间的跳转

故事的流程是通过节点间的跳转来实现的。除了玩家通过点击链接进行跳转外,还可以通过以下方式实现自动跳转:

  • 动作中的 jump 类型:在节点的 "actions" 数组中,可以定义一个 "jump" 类型的动作,使其在进入该节点时自动跳转到另一个节点。

    json
    "linear_path_node": {
        "text": "你别无选择,只能继续前进。",
        "actions": [
            { "type": "jump", "target": "next_scene" }
        ]
    }
  • 监听器触发的跳转:更高级的跳转机制可以通过监听器实现。我们将在后续章节中详细介绍。

理解节点的定义和它们之间的连接方式是构建任何互动故事的基础。在下一章节中,我们将深入探讨 "text" 属性中使用的各种文本格式和标记。