自己紹介
冬ハッカソン25 8班でリードプログラマをしていました、inutamago_dogegg(どぐえぐ)です。今回はプログラムについて挑戦したこと・実践したことを書いていこうと思います。
元ゲームの記事は以下から見れます。

ゲームは以下から遊べます。

冬ハッカソンについて
冬ハッカソンとは、traPで開催されている2つのハッカソンイベントの中で冬に行われるものを指しています。
1週間の準備期間・1週間の制作期間があるのが特徴で、今回は準備が12/8(月)〜14(日)、制作が12/15(月)〜21(日)で行われました。
テーマは「ちょう・あん」でした。
企画
まず、このゲームの企画を聞いた時、「演出の良いボードゲームだな」と思ったため、ビジネスロジックを分離して早めにつくりきる方針にしました。描画部分は後から増やせる構造にして、描画のバグがロジックに波及しないような設計で行きます。
スケジュールとしては以下の想定でした
月曜: ビジネスロジックと軽い描画の完成
火曜: 全ての描画・演出プログラム部分の実装
水曜: 残り部分全てをやってゲームを完成させる
技術選定
アーキテクチャ
ビジネスロジックと描画をちゃんと分離する方針になったため、以前から学習をしていたオニオンアーキテクチャの良い実践機会だと思い設計に組み込みました。
以下はオニオンアーキテクチャについて主に参考にした記事です。


ライブラリ
特に目立った部分は無いです。
以下導入したアセット
- UniTask
- R3
- LitMotion
- TriInspector
- Colorful Hierarchy Category GameObject
- ZString
- VContainer
- Unity NuGet
- Cinemachine
- Text Mesh Pro
R3 は導入したは良いものの一切使っていません。以前に UniRx の使いすぎでゲームフローを追いづらくなってから意識的に使わないようになってしまいました。
TriInspector は Odin Inspector のようにAttributeによって変数を便利にInspectorに表示してくれるアセットです。他にもAlchemyなどの択がありますが、個人的にこれが1番お気に入りです。
開発規則
メインで書くであろうプログラマは何回か一緒に開発したことがあり、特段この規則を強要することは考えていませんでしたが、規則はあった方が良いだろうと思う一応決めてました。
ただ、今回少なくとも6割くらいはコードを書くことになると思っていたので、やりやすいように自分流の規則を多めにしました。
- interface は
IHoge - abstract は
AHoge - private は省略する
- private, protected な変数は
_hoge [SerializeField]が付いていても変えない- public な変数は
Hoge - ブランチの名前は
{イシューの種類}/{イシュー番号}_{イシューの内容}の形 - 例:
feat/10_MiniMap - 基本的に
mainに直プッシュしない
モック作成
このゲームのプログラム自体に慣れるため・テンポ感確認のために準備期間中にモックを作成しました。
ちなみに設計を丸ごと変えた影響でモックのコードは本開発では残っていません。
もっとこの段階でメインの演出入れて厳密なテンポ感を確認できると良かったかな~と思っています。
実際のスケジュール
今回の制作期間は、というか今回もハードな制作になりました。というのも、途中でプログラマメンバーがインフルエンザになり、急遽タスクを巻き取る必要が出てきたからです。
結果として、コア部分の実装から細かい調整まで、かなりの範囲を一人で抱える形になりましたが、気合でなんとか走り切りました。当日のビルドでは、ボタン連打で一気に何階層も降りられてしまうという致命寄りのバグ以外は大きな破綻がなく、トラブルがあっても最低限「遊べる状態」に持っていけたのは素直に良かった点だと思っています。
制作期間中の諸々
Viewにステートマシンを標準搭載した設計
今回の実装で一番効果があった工夫は、Viewクラスに最初からステートマシンを組み込む設計にしたことです。UniTaskベースの非同期ステートマシンを用意し、各Viewが enum で自由に状態を定義できる形にしました。
特にUI周りでは、「ウィンドウ自体の表示状態」と「中身の状態」を分離できるようにしています。ウィンドウ側には Show / Hide / Showing / Hiding の4状態を固定で持たせ、中身のViewはそれとは独立して任意のステートを管理します。これによって、例えば「中身の表示が変化しながらウィンドウ全体としてはフェードアウトする」といった少し複雑な状態遷移も破綻せずに扱えるようになりました。
ステートで網羅しきれない部分はまた別で更新処理を書けば良いので、バグの出にくさとカスタマイズ性の両立ができてて良かったです。
GameScenePresenterに全部詰め込んだ話
一方で、反省寄りの話もあります。ゲーム全体のフロー制御を GameScenePresenter というクラスにほぼ集約したのですが、結果としてかなり巨大なクラスになりました。
ただ、View層とビジネスロジック層自体は細かく分離できていたため、「見通しが完全に壊れる」というほどではありませんでした。とはいえ、ダンジョン部分とギルド部分の両方の処理が混在していたので、ここはステートごとにクラスを分割して責務を整理しておくべきだったなと感じています。
「とりあえず一箇所に集める」判断はスピード面では強いですが、後半の修正コストが確実に跳ね上がるので、次回はもう一段きれいに分割したいポイントです。短期開発なら良い手法かもしれません。
Cursorが想像以上に強かった
今回の開発で最もインパクトが大きかったと思っているのがCursorの活用です。
初のオニオンアーキテクチャの実践はかなり難しいものだと思っていましたが、Cursorのおかげで一気に理論から具体的に実装に落とし込むことができました。AIが書いたコードを見て学習しながら制作を進められたのも大きいです。
あとはプログラムのドキュメント作成が命令1発で大体終わるのが衝撃的でした。「共同作業のために設計とかまとめないとな~」って考えてた時に、AIポン出しだけで十分なクオリティのドキュメントがつくられて本当に助かりました。
全体的な体感としては100倍くらい速くなった感覚になりました。AIにコードを書かせている間に、自分は別の設計や次の仕様決定に頭を回せるため、「考える時間」と「書く時間」を並列化できるのが非常に強力だと思います。
一方で、当然ながら問題もあります。自分が完全に理解しきれていないまま組み込んだコードには、後から見ると負債になりやすい箇所が溜まっていました。短期的な開発速度は大きく上がる一方で、技術的負債の生成速度も同時に上がる、というトレードオフを強く感じました。
結局のところ、「AIに書かせて終わり」ではなく、段階的に人間がレビューして理解を回収していく運用が重要だと思います。今回は時間的にそこまで丁寧に回せなかった部分もあり、次回以降の改善点としてしっかり持ち帰りたいところです。
なお、コーディング自体は Rider を使っていました。IDEとAI補助の組み合わせは普段でも使っていこうと思います。
まとめ
力尽きたので箇条書きにします。
- 結果的に、ビジネスロジックを分離する試みは成功したように思います。
- レイヤー分けによってバグの原因究明が非常にしやすかったです。
- オニオンアーキテクチャ気に入りました。
- Cursor気に入りました。
新しいことに挑戦した上で遊べる状態まで持っていき、色々学びも得られたので良いハッカソンだったな~と思っています。
本編はパワーアップさせて近いうちに展示会に出します。お楽しみに!
余談ですが最近ホームページをつくったのでこちらもぜひご覧くださいー



