ゲーム開発をいい感じに...

@reyu

#traP_LT

自己紹介

  • @reyu
  • 20B 数理・計算科学系
  • traP アルゴリズム班 / CTF班 / ゲーム班 / SysAd班
    • 最近はCTF班でWeb問をよくやっています
#traP_LT

はじめに

  • ゆるいLTです
    • そもそもLTってゆるいものな気もする
  • このスライドはさっき作りました
    • 多分誤字脱字誤情報などがあります
    • 間違えていたりしたらそっと教えて下さい
  • 「ゲーム開発」って言ったんですけどUnityとC#の話が大半です
    • 殴らないでください
  • Q: 「いい感じ」ってどんな感じですか
    • A: いい感じです
#traP_LT

前提 : プロジェクトについて

  • traPにはプロジェクトという制度がある
    • 人を集めてゲーム (とか) を作る
      • プログラム・サウンド・企画・UIデザイン などなど
  • 自分はtraPortationというプロジェクトでプログラムを書いています
    • 交通シミュレーションゲーム
    • Unity 2D / C#
#traP_LT

1年ゲーム開発をして思ったこと①

  • 「タスクを振る」のは難しい
    • 前提知識が必要なら説明しないといけない
      • そもそもどこにも書かれていない前提知識が必要なら多分おかしい
    • 依存関係によってはそもそも手をつけられないタスクがあったり
      • タスク間の依存関係が多すぎてどこから進めればいいのか誰も分からなくなった (実話)
#traP_LT

1年ゲーム開発をして思ったこと②

  • 事前にちゃんと設計をするのは難しい
    • 少なくとも自分には厳しい
      • ゲーム開発の経験の少なさ
      • 「ゲームの設計」の難しさ
#traP_LT

1年ゲーム開発をして思ったこと③

  • 無秩序なコードは読みたくないし変更もしたくない
    • プロジェクトに強制力はあまりないので読みたくないコードは誰も読まない
    • ある程度秩序を保たないとプロジェクトが爆発する
#traP_LT

今回話すこと

  • 「いい感じ」な開発がしたい
    • これは多分全人類そう
  • ゲーム開発をどう「いい感じ」にしていくか
    • 最初から完璧を求めると破滅する
    • だからといって無秩序なまま進めていっても破滅する
#traP_LT

雑な設計 : Unityとそれ以外

  • 世界には2種類のクラスがある
    • MonoBehaviourを継承しているかそうでないか
  • MonoBehaviourを継承しているとどうなる?
    • Unity側でGameObjectに紐づけて使えるようになる
    • Unityの諸機能にアクセスできるようになる
  • C#だけで書ける部分はそうしたほうが扱いやすいし認知コストも下がる
#traP_LT

「設計レベル」を考える

  • Unityにおける「設計レベル」を定義してみた - Qiita
  • 「ハイブリッドなやり方」が紹介されている
    • 純粋なC#で書かれている部分はアーキテクチャなども意識 (レベル4-5)
    • Unityと関わる部分は無秩序にならないようにはしつつもこだわりすぎない (レベル1-2)
#traP_LT

「設計レベル」を考える

Unityにおける「設計レベル」を定義してみた - Qiita より引用

#traP_LT

テストを書きたい

  • Unityだとテストを書くための機能がある
    • Unity Test Runner
  • PlayModeとEditModeがある
    • PlayMode: MonoBehaviourのテストができる
    • EditMode: MonoBehaviourのテストができない
  • GitHubでCI回したりCodeCovとか使ったり色々できる
#traP_LT

今回はEditModeの話をします

  • 自分がPlayModeのテストを書いたことない
  • 設計レベルが高い部分にテストを書くと効果が大きい
    • そういう部分はだいたいEditModeで書けるのでそれで十分なことが多い
#traP_LT

Singletonはアンチパターン?

  • グローバルで1つのインスタンスを使い回したい場面は結構ある
    • ゲームだと GameManager みたいなやつがだいたいいる
  • MonoBehaviourなら GameObject.Find() 、普通のクラスならSingletonを使っていた
  • Singletonはテストを書くときに困りがち (これはゲーム開発に限らず)
#traP_LT

DIContainer

  • UnityだとDIContainerがいくつかある
    • Zenject (Extenject)
    • VContainer
  • 色々機能がついていたりする
    • .AsSingle() / .AsTransient()
    • .FromNew() / .FromNewComponentOnNewGameObject()
    • テストのためのあれこれ
  • MessagePipeというDIContainerを前提にした強いPub/Subライブラリもある
#traP_LT

DIContainerに依存...

  • Zenjectとか使うと曲芸みたいなことが色々できる
  • DIContainer独自の機能に依存しすぎるとあんまりよくない
    • Unityに依存しているのと大差ない
    • 学習コストも発生する
  • DIContainerがなくても実現できることをDIContainerにやらせるぐらいの温度感がちょうどよさそう
    • でもMessagePipeは便利
#traP_LT

C#の言語機能を使おう

#traP_LT

C#の言語機能を使おう : コレクション

  • C#のコレクションには様々なインターフェースが用意されている
  • IReadOnlyList だけでも使えると便利
    • Listとだいたい同等の操作ができる
    • 書き換えはできない
List<Type> list;
public IReadOnlyList<Type> List => this.list;
#traP_LT

C#の言語機能を使おう : null許容参照型

  • C# 8.0
  • null許容参照型
    • 参照型はnullである可能性の考慮が常に必要だった
    • #nullable enable と書くとnullを認めないようにできる
      • T : 通常の参照型
      • T? : null許容参照型
#traP_LT

C#の言語機能を使おう : 他にもいろいろ

  • 使えるといい感じなやつ
    • LINQ
    • switch式 (C# 8.0)
  • まだUnityにないやつ
    • ファイルスコープnamespace (C# 10.0)
    • new型推論 (C# 9.0)
#traP_LT

まとめ

  • ゲームの設計は難しい
    • 適度に妥協しつつ必要なところだけちゃんとやるとよさそう
  • 便利なツールは多いけど...
    • 学習コストとかそのツールへの過度の依存とかは気をつけたほうがいいかもしれない
  • 言語機能は知っているといいことが多い
    • その言語を書くのが好きだと一番良い
#traP_LT