Skip to content

はじめに ​

インストール ​

bash
npm install @lsde/dialog-engine
bash
dotnet add package LsdeDialogEngine

# JSON loader — choose ONE based on your platform:
dotnet add package LsdeDialogEngine.Newtonsoft        # Unity
dotnet add package LsdeDialogEngine.SystemTextJson    # .NET 5+ / Godot .NET
bash
# Add as a git submodule
git submodule add https://github.com/jonlepage/LS-Dialog-Editor-Engine.git deps/lsde

# CMakeLists.txt
add_subdirectory(deps/lsde/lsde-cpp)
target_link_libraries(your_target PRIVATE lsde)
bash
# Copy the headers and source into your project
# e.g. Source/YourModule/ThirdParty/lsde/

cp -r lsde-cpp/include/lsde  YourProject/Source/YourModule/ThirdParty/lsde/include
cp -r lsde-cpp/src/*          YourProject/Source/YourModule/ThirdParty/lsde/src

# In your module's .Build.cs, add:
# PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "ThirdParty/lsde/include"));
# Add the .cpp files from ThirdParty/lsde/src/ to your module
bash
# Clone the repository
git clone https://github.com/jonlepage/LS-Dialog-Editor-Engine.git

# Copy the addon into the Godot project
mkdir -p addons
cp -r LS-Dialog-Editor-Engine/lsde-gdscript/addons/lsde addons/lsde
rm -rf LS-Dialog-Editor-Engine

基本的な使い方 ​

engine はグラフ走査マシンです — block を handler にディスパッチし、ホストアプリケーション側でそれに意味を与えます。handler がなければ、engine は何も出力しません。

フォーマット非依存

engine は BlueprintExport オブジェクトを受け取ります(ファイルではありません)。JSON、XML、YAML のいずれかを、プラットフォームに適したパーサーで読み込んでください。解析とインポートを参照してください。

ts
import { DialogueEngine } from '@lsde/dialog-engine';
import blueprintJson from './blueprints.json';

const engine = new DialogueEngine();
engine.init({ data: blueprintJson });

// Unified condition resolver — evaluates game-state conditions for both
// choice visibility and condition block pre-evaluation.
engine.onResolveCondition((cond) => game.evaluateCondition(cond));

// 3 required handlers — bridge between the engine and your game
// (onCondition is optional when onResolveCondition is installed)
engine.onDialog(({ scene, block, context, next }) => {
  game
    .createDialogAuto(block, context)
    .catch(() => scene.cancel())
    .finally(() => next());
});

engine.onChoice(({ scene, block, context, next }) => {
  game
    .createChoiceAuto(block, context)
    .catch(() => scene.cancel())
    .finally(() => next());
});

engine.onAction(({ block, context, next }) => {
  game
    .executeActions(block.actions)
    .catch((err) => context.reject(err))
    .finally(() => next());
});

// Start a scene anywhere in your game code
function myGameScript(sceneId: string) {
  const scene = engine.scene(sceneId);
  scene.start();
}
csharp
using LsdeDialogEngine;
using LsdeDialogEngine.Json; // LsdeDialogEngine.SystemTextJson package
// Unity: use LsdeDialogEngine.Newtonsoft instead

var blueprint = LsdeJson.Parse(File.ReadAllText("blueprints.json"));
var engine = new DialogueEngine();
engine.Init(new InitOptions { Data = blueprint });

// Unified condition resolver — evaluates game-state conditions for both
// choice visibility and condition block pre-evaluation.
engine.OnResolveCondition(cond => Game.EvaluateCondition(cond));

// 3 required handlers — bridge between the engine and your game
engine.OnDialog(args => {
    var (scene, block, context, next) = args;
    Game.ShowDialog(block, context, onComplete: next);
});

engine.OnChoice(args => {
    var (scene, block, context, next) = args;
    Game.ShowChoices(block, context, onSelected: next);
});

engine.OnAction(args => {
    var (scene, block, context, next) = args;
    Game.ExecuteActions(block.Actions);
    context.Resolve();
    next();
});

// Start a scene anywhere in your game code
void MyGameScript(string sceneId) {
    var scene = engine.Scene(sceneId);
    scene.Start();
}
cpp
#include <lsde/engine.h>

using namespace lsde;

DialogueEngine engine;
engine.init({blueprint});

// Unified condition resolver — evaluates game-state conditions for both
// choice visibility and condition block pre-evaluation.
engine.onResolveCondition([](const ConditionTest& cond) {
    return game->evaluateCondition(cond);
});

// 3 required handlers — bridge between the engine and your game
engine.onDialog([](auto* scene, auto* block, auto* ctx, auto next) -> CleanupFn {
    game->showDialog(block, ctx, [next]() { next(); });
    return {};
});

engine.onChoice([](auto* scene, auto* block, auto* ctx, auto next) -> CleanupFn {
    game->showOptions(block, ctx, [next]() { next(); });
    return {};
});

engine.onAction([](auto*, auto* block, auto* ctx, auto next) -> CleanupFn {
    game->executeActions(block->actions);
    ctx->resolve();
    next();
    return {};
});

// Start a scene anywhere in your game code
auto scene = engine.scene(sceneId);
scene->start();
gdscript
var engine = LsdeDialogueEngine.new()
engine.init({"data": blueprint})

# Unified condition resolver — evaluates game-state conditions for both
# choice visibility and condition block pre-evaluation.
engine.on_resolve_condition(func(cond):
    return game.evaluate_condition(cond)
)

# 3 required handlers — bridge between the engine and your game
engine.on_dialog(func(args):
    await game.show_dialog(args["block"], args["context"])
    args["next"].call()
)

engine.on_choice(func(args):
    await game.show_options(args["block"], args["context"])
    args["next"].call()
)

engine.on_action(func(args):
    game.execute_actions(args["block"].actions)
    args["context"].resolve()
    args["next"].call()
)

# Start a scene anywhere in your game code
func my_game_script(scene_id: String):
    var scene = engine.scene(scene_id)
    scene.start()

Blueprint の検証 ​

engine.init() はエラー、警告、統計情報を含む診断レポートを返します。check オプションでゲーム側の機能とのクロスバリデーションが可能です:

ts
engine.init({
  data,
  check: {
    functions: ['set_flag', 'play_sound'],          // function ids your game implements
    dictionaries: { items: ['sword', 'shield'] },   // dictionary ids and their entry keys
    cards: ['Alice', 'Bob'],                        // card NAMES, never the editor id
  },
});
csharp
engine.Init(new InitOptions {
    Data = blueprint,
    Check = new CheckOptions {
        Functions = new() { "set_flag", "play_sound" },
        Dictionaries = new() { ["items"] = new() { "sword", "shield" } },
        Cards = new() { "Alice", "Bob" },
    },
});
cpp
lsde::CheckOptions check;
check.functions = {"set_flag", "play_sound"};
check.dictionaries = {{"items", {"sword", "shield"}}};
check.cards = {"Alice", "Bob"};

engine.init({blueprint, check});
gdscript
engine.init({
    "data": blueprint,
    "check": {
        "functions": ["set_flag", "play_sound"],
        "dictionaries": {"items": ["sword", "shield"]},
        "cards": ["Alice", "Bob"],
    },
})

25 個の診断 ​

エラー — payload は拒否され、何も再生されません。 errors は空ではなく、engine.scene() は何も返せません。

コード何が起きたか
MISSING_DATAinit() に data が渡されていません
MISMATCHED_EXPORTS別々のエクスポート由来のファイルが混在しています — project か exportedAt が一致しません。1 回のエクスポートのファイルだけを渡してください
WRONG_NAMING_CONVENTIONsnake_case または PascalCase でエクスポートされています。engine が読むのは camelCase です。プロジェクト設定 › エクスポーター › 命名規則
INVALID_FORMATformat が lsde-blueprints ではありません。C# と C++ は上のケースでもこれを報告します:型付きオブジェクトを検証するため、元のキー名はすでに失われています
UNSUPPORTED_FORMAT_VERSIONversion が 1 ではありません。LSDE 1.6 のままのプロジェクトは engine 0.3.x に属します — 二重リーダーはありません
NO_SCENESpayload に scene が 1 つもありません
DUPLICATE_SCENE2 つの scene が path または安定 id を共有しています
MISSING_SCENE_PATHscene に path がありません
DUPLICATE_BLOCK_ID同一 scene の 2 つの block が id を共有しています。scene をまたぐ場合は正当かつ想定どおりです — block は (scene, id) です
INVALID_START_BLOCKscene が、自分の block ではないものを開始 block として指しています
BROKEN_LINKワイヤーが scene に存在しない block を指しています。トラバーサルには行き先がありません

警告 — 再生はされますが、何かが静かに動きません。 読んでください。どれもノイズではありません。

コード何を失うか
NO_START_BLOCKscene に開始 block がないため、start() に始める場所がありません
UNKNOWN_WAIT_BLOCKwaitForBlocks の id が scene の block ではないため、そのトラックは永久に停留します。検証はそれ以上進めません:実在する id でも再生されないことはあり得ます
EMPTY_FUNCTIONaction に関数が選ばれていない呼び出しがあります。ゲームは実行できない呼び出しを受け取ります
UNDECLARED_FUNCTIONaction がエクスポートで宣言されていない関数を呼んでいます — たとえばプロジェクトに残った v1 の id。以前は黙って読み込まれ、ゲーム内で失敗していました
UNDECLARED_ARGUMENT呼び出しが、関数の宣言にない引数を渡しています
UNDECLARED_DICTIONARY_KEYdictionaryKey 引数が、そのパラメーターが指す辞書のエントリではありません
UNDECLARED_DICTIONARYcondition がエクスポートで宣言されていない辞書をテストしています
UNDECLARED_ENTRYcondition が、辞書で宣言されていないエントリをテストしています
UNKNOWN_CHOICE_BLOCK予約辞書 choice のテストが、この scene の CHOICE ではない block を指しています
UNKNOWN_CHOICE_OPTION予約辞書 choice のテストが、その CHOICE にないオプションを指しています
UNKNOWN_FUNCTIONaction が check.functions に無い関数 id を呼んでいます
UNKNOWN_DICTIONARYcondition が check.dictionaries に無い辞書 id をテストしています
UNKNOWN_DICTIONARY_ENTRY辞書は既知ですが、エントリキーが未知です
UNKNOWN_CARDblock が check.cards に無いアクターカードの名前を指しています

最後の 4 つは check を渡したときにだけ現れます — 渡さなければ engine には比較する相手がありません。 その上の 8 つは常に有効です:block が使うものを、エクスポート自身が宣言するものと比べるため、 check は不要です。

scene 内で見つかった診断は sceneId(安定 id sc_…、handle.getSceneId() が返すもの)と scenePath を持ち、 block を指すときは blockId も持ちます。