🦜
Goで3Dゲームエンジン「Lacking」を使う方法
「Lacking」とは

- ほぼPureGoによる3Dゲームエンジン
- ECS(Entity-Component-System)ベース
- Math、Physicsライブラリを内包
- ほぼ同じコードでネイティブ(OpenGL/glfw)でもブラウザでも動作する
- ネイティブオーディオ回りはmini-audio-library依存
- ブラウザではWebGL2、WebAudioを利用している
- 3Dモデルのフォーマットはglfxまたはglbのみサポート
- 必要最低限の機能を抑えたつくり
サンプル
ラリーシミュレーターのデモ
フライトシミュレーターのデモ
キー早打ちによるシューティング
基本的な使い方
あらかじめ必要なもの
- gcc,g++(ネイティブで動かす場合のみ)
- go1.23
- gonew
- task
後者2つのインストール方法
go install golang.org/x/tools/cmd/gonew@latest
go install github.com/go-task/task/v3/cmd/task@latest
プロジェクトを起こす
gonew github.com/nobonobo/lacking-template@latest example.com/your/simplest simplest
cd simplest
ネイティブの実行方法
task pack run
これで以下のような画面が開く

ブラウザでの実行方法
task webpack wasm web # -> run http server on 127.0.0.1:8080
http://127.0.0.1:8080 を開くとほぼネイティブと同じ画面になる

リソースのプレビュー
プロジェクトにて参照しているリソースをプレビューできるstudioという実行ファイルが用意されています。
task preview

HomeScreenをクリック:

フォルダ構成
/
├── Taskfile.yml
├── go.mod
├── go.sum
├── assets/ # assets化(pack/webpack)出力フォルダ
│ └── resources.dat #
├── cmd/
│ ├── game/ # アプリ本体
│ │ └── main.go # ほぼ定型であり編集の必要なし
│ └── studio/ # リソースセット & プレビューア
│ ├── models_home.go # リソースの定義
│ ├── models_play.go # リソースの定義
│ └── main.go # ほぼ定型であり編集の必要なし
├── internal/ # アプリ実装フォルダ
│ ├── game/
│ │ └── data/ # View別のデータ定義
│ └── ui/
│ ├── bootstrap.go
│ ├── global/ # 共通の定義を置く
│ ├── model/ # MVCにおけるModel定義を置く
│ ├── view/ # MVCにおけるViewの定義を置く
│ └── widget/ # UI部品定義を置く
└── resources/ # リソース置き場
├── resources.go
├── raw/ # studio/models_*.goの定義によりassets化される
│ ├── images/
│ └── models/
├── ui/ # resoucrs.goにより実行バイナリにバンドルされる内容
│ └── images/
└── web/ # Web版のテンプレートでtask webpackによりassetsにコピーされる内容
主なフォルダーと役割
- cmd/: 実行ファイル用のコード置く場所
- internal/: プロジェクトのコアロジックを置く場所
- resources/: プロジェクトで利用するリソース群を置く場所
- assets/: アセットファイル置き場(task pack/webpack で自動生成)
- Taskfile.yml: taskコマンド用タスク設定ファイル
何を作る?
まとめ
- これまでに生まれたGo用3Dゲームエンジンは欲張って多機能化し停滞するパターンを繰り返しています
- このLacking-Engineは3Dゲームエンジンとしては欲張らずにミニマムな作りを保っています
- ゲームアプリ構築において必要な機能がそれぞれベストな1つの手法だけがサポートされています
- リッチな3Dエンジンのようにある機能が何通りかの方法で実装されていたりはしません
- そのおかげで、少ない依存でGLまわり、オーディオ、物理エンジンなどをネイティブとWebの両方をサポートすることができています
- こういう依存のシンプルさはGoにマッチしていて、このエンジンで書いたコードは多岐にわたる環境で容易に動かすことができます
- ただ、まだ破壊的変更が入る場合もあるとのことなので要注意です
Discussion