コーディング規約
本ドキュメントは、コードを書くときに守り続ける規約だけを置く。 なぜその規約があるかは ADR、層の責務と契約は アーキテクチャ方針 を参照。
具体的なフォルダツリー・クラス名・シグネチャは書かない。それはコードが正である。
依存の向き
トップレベルのディレクトリは5つ。
| ディレクトリ | 役割 |
|---|---|
core/ | ゲームの状態と規則。Node を一切含まない |
data/ | .tres によるデータ定義 |
presentation/ | シーンと View。Node を含む |
app/ | 合成ルート・シーン遷移・セーブIO |
dev/ | 開発者モードのオーバーレイ |
依存は常に 他の全て → core/ の一方向である。core/ が presentation/ や app/ を参照することは、いかなる理由があっても禁止する。
Autoload は app/ のもの1つだけにする。増やすと、どこからでも状態に触れる経路ができ、契約1 が壊れる。
godot_aiアドオンが登録する_mcp_game_helperは開発支援用であり、ゲームロジックとは無関係である。
core/ の禁止事項
以下はバグではなく設計違反として扱う。
| 禁止すること | 理由 |
|---|---|
Node の継承、SceneTree / get_tree() / Input の参照 | ヘッドレステストが成立しなくなる(ADR-0011) |
await・シグナル | 演出の待ちが状態層に侵入する(ADR-0012) |
randi() / randf() / Array.shuffle() | グローバル乱数はセーブで再現できない(ADR-0013) |
| Intent を経由する以外の状態変更 | 開発者モードの操作も例外ではない(ADR-0014) |
| 型なし変数 | 層をまたぐ誤った参照をエディタが検出できなくなる |
| 子から親への参照 | RefCounted の相互参照はリークする。必要な文脈は引数で渡す |
@tool | エディタ実行時に副作用が走る |
| イベントに演出情報を載せること | アニメーション名・色・座標・演出時間は表現層が決める |
シャッフルが必要な場合は、状態層が所有する乱数を使って Fisher-Yates を自前で実装する。
命名規約
| 対象 | 規約 | 例 |
|---|---|---|
| ファイル名 | snake_case.gd | battle_state.gd |
| クラス名 | PascalCase | BattleState |
| Intent | 〜Intent | PlayPageIntent |
| Event | 〜Event | PagePlayedEvent |
| 定義 Resource | 〜Def | PageDef |
| 実行時インスタンス | 〜Instance | PageInstance |
| 拒否理由 | StringName の snake_case | &"not_enough_ho" |
ゲーム用語はドキュメントと同じ語を使う。 toki(刻)・mei(銘)・hokorobi(綻び)・guard(防御)をそのままコード上の名前にし、独自の英訳を発明しない(用語集)。
効果に型を作らない
「効果1つ = クラス1つ」という対応を作らない(ADR-0035)。効果の単位は作用であり、それは6項を持つデータである(効果システム)。打点が2発あるページは、敵HPへの作用を2つ並べるのであって、2つの効果クラスを持つのではない。
〜Effect は例外にだけ付ける。 作用の文法で表現できない振る舞いが出てきたときに限りクラスを書き、なぜ文法で書けないのかをそのとき記録する。 既定は常に作用の列である。
よく使う作用の組み合わせに名前を付けない。 分類が要るようになってから付ければよく、それはプレイ体験を確かめるまで決められない。先に名前を付けると型の単位になり、そこから仕様の語彙へ逆流する。
コメント
書くのは、隠れた制約・非自明な不変条件・特定のバグの回避策・読み手が驚く振る舞いがあるときだけである。 コードが何をするか(WHAT)を言い換えるだけのコメントは書かない。
長さは内容が決める。 必要なことが必要な分量だけ書かれていればよく、1行に収めることが目的ではない。説明に3行要るなら3行書く。ただし gdlint の100文字制限はコメントにも掛かるので、長い説明は複数の ## 行に折り返す。短く見せるために1行へ押し込むと、読みにくいコメントと lint 違反の両方を招く。
Issue 番号・受け入れ条件の番号・テストIDをソースコメントに書かない。 これらは Issue が閉じた時点で陳腐化し、コードだけを読む人には辿れない。設計判断の背景・トレードオフ・検討して却下した案は、コミットメッセージ・PR 本文・ADR に置く — そこは変更の経緯を追う場所として残り続ける。
定義と実行時インスタンスを分ける
.tres は定義である。盤面上の1枚が持つ状態(各面が白紙か・書かれているか・ペンで強化済みか)は、定義とは別のオブジェクトに置く。
.tres から load() したインスタンスを実行時に書き換えてはならない。 Godot の Resource はデフォルトでキャッシュ共有されるため、書き換えると同じ定義を使う全ての札に波及する(ADR-0010)。
Godot 4.7 の罠
| 項目 | 注意 |
|---|---|
| レンダラ | GL Compatibility で動作すること。Forward+ 専用機能を使わない |
| Resource のキャッシュ | load() した Resource は共有される(→ 上節) |
Array[T] の @export | 使用可能。ただし型を持たない Array との混在に注意 |
RefCounted の循環参照 | 相互参照はリークする。親への参照を持たせない |
class_name の循環 preload | GDScript は循環 preload に弱い |