はじめに
インストール
bash
npm install @lsde/dialog-enginebash
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 .NETbash
# 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 modulebash
# 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_DATA | init() に data が渡されていません |
MISMATCHED_EXPORTS | 別々のエクスポート由来のファイルが混在しています — project か exportedAt が一致しません。1 回のエクスポートのファイルだけを渡してください |
WRONG_NAMING_CONVENTION | snake_case または PascalCase でエクスポートされています。engine が読むのは camelCase です。プロジェクト設定 › エクスポーター › 命名規則 |
INVALID_FORMAT | format が lsde-blueprints ではありません。C# と C++ は上のケースでもこれを報告します:型付きオブジェクトを検証するため、元のキー名はすでに失われています |
UNSUPPORTED_FORMAT_VERSION | version が 1 ではありません。LSDE 1.6 のままのプロジェクトは engine 0.3.x に属します — 二重リーダーはありません |
NO_SCENES | payload に scene が 1 つもありません |
DUPLICATE_SCENE | 2 つの scene が path または安定 id を共有しています |
MISSING_SCENE_PATH | scene に path がありません |
DUPLICATE_BLOCK_ID | 同一 scene の 2 つの block が id を共有しています。scene をまたぐ場合は正当かつ想定どおりです — block は (scene, id) です |
INVALID_START_BLOCK | scene が、自分の block ではないものを開始 block として指しています |
BROKEN_LINK | ワイヤーが scene に存在しない block を指しています。トラバーサルには行き先がありません |
警告 — 再生はされますが、何かが静かに動きません。 読んでください。どれもノイズではありません。
| コード | 何を失うか |
|---|---|
NO_START_BLOCK | scene に開始 block がないため、start() に始める場所がありません |
UNKNOWN_WAIT_BLOCK | waitForBlocks の id が scene の block ではないため、そのトラックは永久に停留します。検証はそれ以上進めません:実在する id でも再生されないことはあり得ます |
EMPTY_FUNCTION | action に関数が選ばれていない呼び出しがあります。ゲームは実行できない呼び出しを受け取ります |
UNDECLARED_FUNCTION | action がエクスポートで宣言されていない関数を呼んでいます — たとえばプロジェクトに残った v1 の id。以前は黙って読み込まれ、ゲーム内で失敗していました |
UNDECLARED_ARGUMENT | 呼び出しが、関数の宣言にない引数を渡しています |
UNDECLARED_DICTIONARY_KEY | dictionaryKey 引数が、そのパラメーターが指す辞書のエントリではありません |
UNDECLARED_DICTIONARY | condition がエクスポートで宣言されていない辞書をテストしています |
UNDECLARED_ENTRY | condition が、辞書で宣言されていないエントリをテストしています |
UNKNOWN_CHOICE_BLOCK | 予約辞書 choice のテストが、この scene の CHOICE ではない block を指しています |
UNKNOWN_CHOICE_OPTION | 予約辞書 choice のテストが、その CHOICE にないオプションを指しています |
UNKNOWN_FUNCTION | action が check.functions に無い関数 id を呼んでいます |
UNKNOWN_DICTIONARY | condition が check.dictionaries に無い辞書 id をテストしています |
UNKNOWN_DICTIONARY_ENTRY | 辞書は既知ですが、エントリキーが未知です |
UNKNOWN_CARD | block が check.cards に無いアクターカードの名前を指しています |
最後の 4 つは check を渡したときにだけ現れます — 渡さなければ engine には比較する相手がありません。 その上の 8 つは常に有効です:block が使うものを、エクスポート自身が宣言するものと比べるため、 check は不要です。
scene 内で見つかった診断は sceneId(安定 id sc_…、handle.getSceneId() が返すもの)と scenePath を持ち、 block を指すときは blockId も持ちます。
