ライフサイクルと検証
完全なライフサイクル
各 Block の実行順序
- 前の block のクリーンアップ — 前の block の handler が返したクリーンアップ関数が遷移時に実行されます(
next()が呼ばれた時点) onValidateNextBlock— 実行前の検証onBeforeBlock— 前処理(続行するにはresolve()を呼び出す必要あり)- タイプ handler(Tier 2、次に Tier 1)
Scene イベント
ts
engine.onSceneEnter(({ scene, context }) => {
// Called when handle.start() is executed
});
engine.onSceneExit(({ scene, context }) => {
// Called when the scene ends (naturally or via cancel)
});csharp
engine.OnSceneEnter(args => {
// Called when handle.Start() is executed
});
engine.OnSceneExit(args => {
// Called when the scene ends (naturally or via cancel)
});cpp
engine.onSceneEnter([](auto* scene, auto*) {
// Called when handle->start() is executed
});
engine.onSceneExit([](auto* scene, auto*) {
// Called when the scene ends (naturally or via cancel)
});gdscript
engine.on_scene_enter(func(args):
pass # Called when handle.start() is executed
)
engine.on_scene_exit(func(args):
pass # Called when the scene ends (naturally or via cancel)
)onValidateNextBlock
各 block 遷移をインターセプトして検証します。handler は次の block (nextContext) と前の block (fromContext) の解決されたキャラクターを受け取ります:
ts
engine.onValidateNextBlock(({ nextBlock, fromBlock, nextContext, fromContext }) => {
return { valid: true };
});
engine.onInvalidateBlock(({ scene, reason }) => {
console.error('Invalid block:', reason);
scene.cancel();
});csharp
engine.OnValidateNextBlock(args => {
// args.NextContext.Character, args.FromContext?.Character
return new ValidationResult { Valid = true };
});
engine.OnInvalidateBlock(args => {
Console.Error.WriteLine($"Invalid block: {args.Reason}");
args.Scene.Cancel();
});cpp
engine.onValidateNextBlock([](const auto& args) {
// args.nextContext.character, args.fromContext.character (check args.hasFromContext)
return ValidationResult{true};
});
engine.onInvalidateBlock([](auto* scene, const auto& reason) {
std::cerr << "Invalid block: " << reason << "\n";
scene->cancel();
});gdscript
engine.on_validate_next_block(func(args):
# args["nextContext"]["character"], args["fromContext"]["character"]
return {"valid": true}
)
engine.on_invalidate_block(func(args):
printerr("Invalid block: %s" % args["reason"])
args["scene"].cancel()
)Character Gating
nextContext.character を使用して、ゲームの状態に基づいて block の実行を制御します:
ts
// Block if the character is stunned
engine.onValidateNextBlock(({ nextContext }) => {
const { character } = nextContext;
if (!character) return { valid: false, reason: 'no_character' };
if (game.characterHasStatus(character, 'stunned'))
return { valid: false, reason: 'character_stunned' };
return { valid: true };
});csharp
engine.OnValidateNextBlock(args => {
var character = args.NextContext.Character;
if (character == null)
return ValidationResult.Fail("no_character");
if (game.CharacterHasStatus(character, "stunned"))
return ValidationResult.Fail("character_stunned");
return ValidationResult.Ok();
});cpp
engine.onValidateNextBlock([&game](const auto& args) {
auto* character = args.nextContext.character;
if (!character) return ValidationResult{false, "no_character"};
if (game.characterHasStatus(character, "stunned"))
return ValidationResult{false, "character_stunned"};
return ValidationResult{true};
});gdscript
engine.on_validate_next_block(func(args):
var character = args["nextContext"]["character"]
if character == null:
return {"valid": false, "reason": "no_character"}
if game.character_has_status(character, "stunned"):
return {"valid": false, "reason": "character_stunned"}
return {"valid": true}
)fromContext.character を使用してキャラクター間の遷移を検証できます(例:関係チェック、クールダウン)。fromContext はシーンの最初の block では null です。
onBeforeBlock
各 block の前に呼び出されます。続行するには必ず resolve() を呼び出す必要があります:
ts
engine.onBeforeBlock(({ block, resolve }) => {
const delay = block.nativeProperties?.delay;
if (delay) {
setTimeout(resolve, delay * 1000);
} else {
resolve();
}
});csharp
engine.OnBeforeBlock(args => {
var delay = args.Block.NativeProperties?.Delay;
if (delay.HasValue)
{
// use your engine's delay system (coroutine, DOTween, Invoke, etc.)
DelayThenCall((float)delay.Value, args.Resolve);
}
else
{
args.Resolve();
}
});cpp
engine.onBeforeBlock([](const auto& args) {
auto delay = args.block->nativeProperties
? args.block->nativeProperties->delay : std::nullopt;
if (delay.has_value()) {
// use your engine's timer system (FTimerManager, SDL_AddTimer, etc.)
scheduleDelay(delay.value(), [&args]() { args.resolve(); });
} else {
args.resolve();
}
});gdscript
engine.on_before_block(func(args):
var delay = args["block"].get("nativeProperties", {}).get("delay", 0)
if delay > 0:
await get_tree().create_timer(delay).timeout
args["resolve"].call()
)クリーンアップ関数
handler はクリーンアップ関数を返すことができ、block から離れる際に呼び出されます:
ts
engine.onDialog(({ block, next }) => {
const element = showDialogUI(block);
// next() is called later — by player input, timer, etc.
return () => {
element.remove(); // called when the engine moves to the next block
};
});csharp
engine.OnDialog(args => {
var element = ShowDialogUI(args.Block);
// next() is called later — by player input, timer, etc.
return () => element.SetActive(false);
});cpp
engine.onDialog([](auto*, auto* block, auto* ctx, auto next) -> CleanupFn {
auto* element = showDialogUI(block);
// next() is called later — by player input, timer, etc.
return [element]() { element->remove(); };
});gdscript
engine.on_dialog(func(args):
var element = show_dialog_ui(args["block"])
# next is called later — by player input, timer, etc.
return func(): element.queue_free()
)エラー境界
すべての handler 呼び出しは try/catch でラップされています。handler がスローした場合:
- エラーはサイレントです — ログ出力や再スローは行われません。scene が予期せず終了した場合、handler を確認してください。
- メイントラックの場合:scene はクリーンに終了します
- async トラックの場合:影響を受けたトラックのみが終了し、他のトラックとメインフローは継続します
これはクロス言語互換です(TS、C#、C++、GDScript の try/catch)。
cancel()
scene.cancel() を呼び出すと、以下のシーケンスが実行されます:
- すべての async トラック がキャンセルされます
- 現在の block のクリーンアップ関数が実行されます
onSceneExithandler が呼び出されます- scene が完了としてマークされます
ts
engine.onInvalidateBlock(({ scene, reason }) => {
console.error('Validation failed:', reason);
scene.cancel();
});csharp
engine.OnInvalidateBlock(args => {
Console.Error.WriteLine($"Validation failed: {args.Reason}");
args.Scene.Cancel();
});cpp
engine.onInvalidateBlock([](auto* scene, const auto& reason) {
std::cerr << "Validation failed: " << reason << "\n";
scene->cancel();
});gdscript
engine.on_invalidate_block(func(args):
printerr("Validation failed: %s" % args["reason"])
args["scene"].cancel()
)NativeProperties
engine が block をディスパッチする方法を制御する実行プロパティ:
| フィールド | 型 | 説明 |
|---|---|---|
isAsync | boolean? | 並列 async トラックで実行 |
delay | number? | 実行前のディレイ(onBeforeBlock で消費) |
timeout | number? | 実行タイムアウト |
portPerCharacter | boolean? | metadata 内のキャラクターごとに出力ポートを作成 |
skipIfMissingActor | boolean? | 参照されたアクターが不在の場合、block をスキップ |
debug | boolean? | エディタ用デバッグフラグ |
waitForBlocks | string[]? | この block が進行する前に訪問済みでなければならない block の UUID |
waitInput | boolean? | 明示的なプレイヤー入力制御用のパッシブフラグ |
