MitiruEngine

アーキテクチャ

MitiruEngine の技術スタック、レイヤー構成、性能特性、既知の制限を、誇張なしで一枚にまとめたページ。

MitiruEngine は C++ で書くゲームロジックHTML/CSS/JS で書く UI を、薄い signal-only bridge で繋いだヘッダオンリーのゲームエンジンです。このページは、エンジンの中身を「速い部分」「遅い部分」「未対応の部分」まで含めて開示することを目的にしています。

1. 1 行サマリ

エンジンコア (game loop / scene / ECS / asset / audio / input / graphics / save / network / physics) は header-only な C++20 として include/mitiru/ 配下に展開され、#include <mitiru/Mitiru.hpp> 1 行から段階的に利用できます。画面に出る UI / HUD / 演出は CEF (Chromium Embedded Framework) 上の HTML/CSS/JS で組み、両者は「JS → C++ は入力 event のみ」「C++ → JS は view update のみ」という薄い bridge で連絡します。

2. レイヤー図

3 層構成です。矢印は bridge を通る方向と内容を示します。

MitiruEngine の 3 層構成図 最上層に CEF で動く HTML/CSS/JS の UI 層、中央に signal-only な bridge、最下層に C++20 のエンジンコアが位置する。 View 層 — CEF 128.4 (HTML / CSS / JS) メニュー / HUD / ダイアログ / トランジション / typewriter / モーダル web/mitiru_runtime/*.js (22 モジュール) + ゲームごとの HTML / CSS Signal-only Bridge JS → C++ : 入力 event のみ / C++ → JS : view update 通知のみ C++20 Engine Core (header-only) game loop / scene / ecs / asset / resource / audio / input / render / gfx data / save / network / physics / fsm / narrative / observe / validate Graphics: DX12 / DX11 / Vulkan / OpenGL / WebGL2 / Null JS event handler dispatch view update DOM patch
図 1: 3 層 (CEF view / signal-only bridge / C++ engine core)

コンポーネント図

C++ コアの主な subsystem と、CEF view 側で動く JS runtime を並べたものです。

エンジン subsystem とランタイム JS モジュールの構成 C++ コアは core / scene / ecs / render / gfx / audio / input / data / save / network / physics / cef / bridge を含む。CEF view 側には router / state / hud / chat / novel / drag / modal などの runtime モジュールが対応する。 C++ Engine Core (header-only) core / loop scene ecs fsm render gfx (DX12) gfx (Vulkan) gfx (OpenGL) gfx (DX11) gfx (WebGL2) gfx (Null) platform audio input resource asset data (JSON) save network physics narrative vn i18n world animation sprite effects ui cef (host) bridge observe validate debug math / util time server JS Runtime (CEF 内) mitiru_runtime / router / state hud / chat / modal / preloader novel / transitions / audio drag / input / physics i18n / content / save cef_state / debug / telemetry crash_reporter / test_harness anchored_entity / inspector 22 モジュール (web/mitiru_runtime/) 画面の見た目とアニメーションのみ gameplay state は持たない
図 2: C++ subsystem (約 44 ディレクトリ) と JS runtime (22 モジュール) の対応

データフロー (入力 → 状態 → 描画)

入力 → C++ ロジック → 状態更新 → 描画、という 1 フレームの大まかな流れです。

1 フレームのデータフロー ユーザ入力が InputMapper を通って C++ のゲームロジックに渡り、状態が更新されたあと CEF / Native renderer の両出口から画面に出る流れ。 入力デバイス Keyboard / Mouse Gamepad / Touch InputMapper (C++) raw → Action enum Jump / Fire / Pause ゲームロジック (C++) SceneRouter / StateMachine ECS / physics / AI 状態 (C++ 所有) HP / score / scene cef::StateStore Native Renderer Renderer2D / Renderer3D DX12 / Vulkan / OpenGL CEF View (HTML/CSS) HUD / menu / dialog Mitiru.state.subscribe 画面 (compositor 出力) 毎フレーム (60Hz target)
図 3: 1 フレームのデータフロー。入力は C++ で意味を持ち、状態は C++ 側が所有し、描画は Native renderer と CEF view の 2 系統に分かれて compositor に合流する。

ビルドパイプライン

ソースからユーザに渡る実行ファイル (+ CEF runtime 同梱) までの流れです。

ビルドパイプライン C++ ヘッダと HTML/CSS/JS の両入力を CMake が束ね、MSVC または Clang/GCC でコンパイルし、最終的に exe と CEF runtime 一式を同梱して配布する。 C++20 ヘッダ + .cpp include/mitiru/ ~700 hpp HTML / CSS / JS web/mitiru_runtime/ + assets 3rd-party submodule CEF / Jolt / sgc / stb 他 JSON (content / save) balance / i18n / scenario CMake 3.21+ cmake --preset default MITIRU_HEADER_ONLY=ON MITIRU_DISABLE_CEF (opt) Compiler MSVC (primary) Clang / GCC emcc (WebAssembly) exe ゲーム本体 CEF runtime libcef.dll 等 Header-only モードでは consumer 側で TU ごと inline
図 4: ビルドパイプライン。CMake が C++ / web / submodule / JSON を束ね、コンパイラを通って exe と CEF runtime 一式が出力される。配布は exe + 同梱 dll セット。

CEF プロセスモデル (single-process workaround の位置)

通常の CEF は複数プロセス構成ですが、本エンジンは現状 --single-process で 1 プロセスに集約しています (詳細は §5.3)。下図は両構成を並べたものです。

CEF プロセス構成: 通常 (multi-process) と現状 (single-process) 通常 CEF は browser/renderer/gpu/utility/helper の複数プロセスに分離するが、MitiruEngine は現状 --single-process で 1 プロセスに集約している。 通常の CEF (multi-process) Browser (host) Engine 本体 main thread UI / IPC 集約 Renderer V8 / DOM / JS GPU process accelerated compositor Utility network / audio Helper / Plugin subprocess.exe 通信は IPC (Mojo) GPU クラッシュは browser を巻き込まない MitiruEngine 現状: --single-process (workaround) 1 プロセスに集約 Browser/Host Engine main Renderer V8 / DOM GPU compositor Utility network 等 理由 subprocess の spawn が error_code=63 で FATAL に なる環境への暫定対策 代償: クラッシュ分離なし
図 5: CEF プロセス構成。上は本来の multi-process 構成、下は現状の MitiruEngine が採用している --single-process workaround。後者は GPU / V8 が host と同一プロセスに同居するため、クラッシュ分離を失う代わりに subprocess spawn 問題を回避している。詳細は §5.3。

3. 技術スタック

実態は CMakeLists.txtinclude/mitiru/external/ から読み取った内容です。推測なし。

項目 採用
言語 C++20 (cxx_std_20CMakeLists.txt で要求)
ビルドシステム CMake 3.21+、cmake --preset default 対応
形態 Header-only INTERFACE library (MITIRU_HEADER_ONLY=ON がデフォルト、約 700 個の .hpp) / STATIC ビルドも可 (MITIRU_HEADER_ONLY=OFF)
対応 OS Windows (primary、DX12 + CEF + DX11 が完動)、Linux / macOS (best-effort、Vulkan + OpenGL)、Emscripten (WebAssembly + WebGL2)
Graphics backend DX12 / DX11 (Windows) / Vulkan (Linux + macOS via MoltenVK / Windows) / OpenGL (SDL2 or GLFW) / WebGL2 (Emscripten) / NullDevice (headless)
Window backend Win32Window / GlfwWindow / Sdl2Window / WebGL canvas
UI 層 CEF 128.4.12 (Chromium Embedded Framework)、MITIRU_DISABLE_CEF=ON で除外可
JSON nlohmann/json + NLOHMANN_DEFINE_TYPE_* マクロ規約 (詳細は §4)
Audio miniaudio (デスクトップ) / WebAudio (Emscripten) / PulseAudio (Linux 検出時) / NullAudioEngine
Save schema Versioned envelope + MigrationChain<T> (include/mitiru/data/SaveSchema.hpp)
Profiling Tracy zones (include/mitiru/debug/TracyZones.hpp、オプション有効化)
Networking GameNetworkingSockets opt-in (MITIRU_ENABLE_GNS=ON)、デフォルトは NullReliableTransport スタブ
3rd-party (submodule) sgc / mml / stb / tinyobjloader / miniaudio / cgltf / nanovg、Chromium 派生は CEF binary distribution として外部から取得
Test framework Catch2 v3 (ctest --test-dir build -C Debug)、最新 main で 2259 件 green
ライセンス MIT

4. 主要な設計判断

エンジン設計の根幹となる 3 つの判断を簡潔にまとめます。

  • C++ ゲームプレイ + CEF は View 専用: 当初 hybrid runtime (gameplay を JS で書く) として開始しましたが、二言語境界の認知負荷、V8 GC 由来の frame drop、CEF subprocess 問題などから「gameplay は C++、CEF は view 専用」に方針転換しました。bridge は signal-only に絞り、状態は C++ 側に一元化しています。
  • scripting 言語を embed しない: Lua / Squirrel / GDScript 等の embed をやめ、Siv3D をロールモデルに pure C++ 路線を採用しました。Lua VM / NodeGraph / LuaCodeGen 等を全削除しています。iteration speed は MITIRU_HEADER_ONLY=ON の incremental compile と asset hot reload で確保します。
  • JSON binding: nlohmann macros + Versioned envelope: codegen / external reflection に頼らず、NLOHMANN_DEFINE_TYPE_INTRUSIVE ベースの 1 行マクロと MigrationChain<T> で save / content / balance すべての JSON I/O を統一しました。std types を直接使う方針 (std::string / std::vector / std::optional を独自エイリアスで隠さない) もこの延長です。

5. パフォーマンス特性

このセクションは「速い部分」「重い部分」「未対応の部分」を分けて、できるだけ正直に書きます。実測がない箇所は明示的に「未計測」と書きます。

5.1 速い部分

  • C++20 gameplay は普通のネイティブ速度で動く: DX12 backend は Windows + GPU 環境で完動し、60 FPS を目標とした game loop が前提です。include/mitiru/core/GameLoop.hppFrameTimer.hpp で固定タイムステップを実装しています。
  • header-only による inline 効きやすさ: MITIRU_HEADER_ONLY=ON がデフォルトのため、consumer 側の translation unit ごとに inline 最適化が効きます。トレードオフは consumer 側ビルド時間 (PCH 推奨)。
  • bridge 通信量は基本的に小さい: JS → C++ は input event のみ、C++ → JS は view update のみで、典型的なフレームでは数 event / 数 KB 以下に収まります。
  • ECS / scene graph は header-only: include/mitiru/ecs/include/mitiru/scene/ 配下に展開され、prefab / system scheduler / component registry を直接 inline 利用できます。

5.2 重い部分 (実測値の有無を明記)

  • CEF の off-screen rendering pipeline: CEF は OSR (off-screen render) → C++ 側でテクスチャに転送 → GPU upload という経路で画面に出ます。1280x720 RGBA で 1 フレームあたり約 3.5 MB の転送が発生する計算で、60 FPS なら約 210 MB/s のバンド幅を消費します。これは無視できないコストです (帯域は理論値、実測スループットは未計測)。
  • CEF の起動コストと配布サイズ: libcef.dll だけで 100 MB 級、Resources/locales/*.pak 一式を含めるとコールドスタート 1〜3 秒 (環境依存、実測は未取得)。CEF を使わないゲームには MITIRU_DISABLE_CEF=ON を用意しています。
  • ベースラインメモリ: CEF + Chromium + V8 を含む構成で常駐メモリは数百 MB オーダー (実測未取得)。軽量 2D ゲームには CEF を外す選択肢が現実的です。
  • JS → C++ event レイテンシ: single-process 構成で 1〜3 ms 程度の目安 (Chromium IPC の公開ベンチからの推定で、本リポジトリでの実測は未取得)。60 FPS のユーザー操作には十分ですが、毎フレーム数百 event を要する用途には不向きです。

5.3 既知の制限

  • CEF subprocess launch failed: error_code=63: 一部の Windows 環境で GPU process が spawn できず FATAL 終了する問題が継続しています。現状の workaround として --single-process モードを include/mitiru/cef/MitiruCefApp.hpp:94-107 に hard-coded しています。原因の最有力候補は libcef.dll (Release /MD) と consumer 側 (Debug /MDd) の CRT mismatch で、cmake/MitiruCef.cmake で subprocess 専用の /MD wrapper を分けてビルドする対策を入れています。詳細: docs/CEF_SUBPROCESS_DIAGNOSTIC.md / docs/CEF_CRT_EXPERIMENT.md
  • --single-process モードの弊害: GPU process が分離されないため、CEF クラッシュがホストプロセスを巻き込みます。本番リリース向けにはリスクが残り、根本対策は継続調査中です。
  • Linux / macOS は best-effort: primary tested path は Windows + DX12 + CEF。Linux は Vulkan + GLFW、macOS は MoltenVK 経由を前提に検出ロジックを書いていますが、CI による全 backend テストの coverage は限定的です。
  • WebGL build は実験段階: Emscripten 向けの WebGL2 backend (include/mitiru/gfx/webgl/) と WebAudio は存在しますが、CEF は WebAssembly 環境では動かないため、UI 層の代替設計が必要です (現状未整備)。

5.4 ベンチ数値

現時点で公開できる数値は次のとおりです (実測なしの項目は「未計測」と明記)。

項目
Catch2 テスト件数 2259 件 green (main、2026-05-15 時点)
Header-only ファイル数 約 700 個の .hpp
CEF テクスチャ転送 (1280x720 RGBA, 60 FPS) 約 210 MB/s (理論値、実測未取得)
Frame budget (target 60 FPS) 16.6 ms / frame (gameplay + render + CEF compositor)
ECS query / pathfinding / JSON parse スループット 未計測 (公式 bench は今後追加予定)

6. 他エンジンとの違い

特定エンジンを下げる意図はありません。同じ「2D + scripted scene 中心のゲーム制作」ニーズに対する、それぞれのアプローチの違いです。

エンジン アプローチ 強み MitiruEngine との違い
Unity C# + visual editor + asset store エコシステム規模、エディタ機能、商用サポート MitiruEngine は scripting 言語を持たず、IDE エディタも提供しません。ゲーム作者の手は常に C++ にあります。
Unreal Engine C++ + Blueprint + visual editor AAA 規模、フォトリアル、巨大エコシステム MitiruEngine は 2D / UI 中心、ヘッダオンリー、配布バイナリが小さい設計です。
Godot GDScript + C# + 統合エディタ OSS、軽量、エディタ統合 MitiruEngine は IDE エディタを作らず、UI は HTML/CSS で書きます。
Siv3D (OpenSiv3D) Pure C++ ライブラリ、Main.cpp から書く C++ 学習向け、依存が少ない MitiruEngine も pure C++ ですが、CEF を view 層として分離している点が違います。Siv3D は同一プロセスで全描画を完結します。
Phaser / Pixi.js JavaScript / TypeScript engine、Web first Web 配布、ブラウザで即動く MitiruEngine は native binary。CEF は UI 層に限定しており、gameplay は C++ で書きます。

7. ロードマップと制限事項

  • IDE / visual editor は作らない方針: 人間 + テキストエディタ + asset hot reload で十分という前提です。エディタ統合のコストを払わない代わりに、C++ ヘッダの API surface を直接配布しています。
  • 3D は 2D と同等の重みで開発中 (実態): include/mitiru/render/ には 3D 系ヘッダが多数あります — Camera3D / Mesh / Scene3D / Pipeline3D / GBuffer / DeferredPipeline / ShadowMap / ShadowSystem / SSAOEffect / DepthOfFieldEffect / TAAEffect / FSREffect / GlobalIllumination / VolumetricLighting / ClusteredLighting / MultiLightSystem / DecalSystem / Billboard3D / ParticleSystem3D / Sprite3DRenderer / OffscreenRenderer3D / GpuSkinning / SkeletalAnimation / InstancedRenderer / FrustumCulling / OcclusionCuller / LODSystem / Skybox / Cubemap / PBRMaterial / PBRShaders / NPRShaders3D / ToonPipeline / GltfLoader / ObjLoader ほか。3D physics は include/mitiru/physics/ 配下の PhysicsWorld3D / PhysicsSystem3D / RigidBody3D / Collider3D / BroadPhase3D / NarrowPhase3D / ContactSolver3D / Constraints3D / CollisionDetection3D / PhysicsDebugRenderer3D (10 ファイル) と、Jolt Physics 統合 (JoltPhysics.hpp、外部 submodule external/jolt/ がある場合に有効化、なければ NullJoltPhysicsWorld スタブにフォールバック) で構成されます。描画 backend (DX12 / Vulkan / OpenGL) も 2D と 3D 両方を通します。残っているのは「3D 専用 example の本数を増やすこと」「Jolt 連携の安定運用検証」「production-grade な GI / PBR 仕上げの確認」で、エンジン基盤としては揃っています。
  • 3D 用 example の拡充: 描画 / 物理ともにヘッダは揃っていますが、エンドツーエンドの 3D サンプル本数は 2D に比べてまだ少なめです。include/mitiru/render/Renderer3D.hpp / Renderer3D_DX12.hpp / Scene3D.hpp を使った最小サンプルを順次追加していく予定です。
  • 3D physics (Jolt) の安定化: Jolt Physics は MSVC で CRT mismatch を避けるため MSVC_RUNTIME_LIBRARY を明示的に揃えていますが (CMakeLists.txt 第 489 行付近)、長時間運用での挙動確認は継続中です。Jolt が見つからない環境では NullJoltPhysicsWorld スタブにフォールバックする仕組みになっており、3D physics が必須でない build もそのまま通ります。
  • Multiplayer は実験段階: include/mitiru/network/ に抽象化はあるものの、GameNetworkingSockets 連携 (MITIRU_ENABLE_GNS=ON) はオプトインで、本番運用実績はまだありません。
  • CEF subprocess 問題の根本対策: --single-process workaround 依存を解消する作業が継続中です (CRT mismatch 仮説の検証込み)。
  • WebAssembly distribution: WebGL2 backend は存在しますが、CEF を前提とした UI を WebAssembly 上でどう代替するかは未着手です。

8. ソースと公開状況

  • Engine source: GitHub mogmog-0110/MitiruEngine — MIT、public
  • Site source: 本サイトのソースも上記 public リポジトリの site/ 配下に同梱されています。
  • API リファレンス: API Reference を参照