こんにちは、Unityエンジニアのオオバです。
Unityでゲームづくり開始直後って 「暇」 ですよね。
特にUnityエンジニアは。
- ゲーム企画が決まらない
- UIもない
- イラストもアニメーションもない
- 3Dキャラクタもない
つまり 「作業したくても作業が見つからない状態」 なんですよね。
暇な状態は 非常にもったいない です!!
探せばやることはたくさんあります。むしろ、開発初期だからこそやっておくべきこと がめちゃくちゃあります。
そこで過去に新規ゲームを10本以上、イチから立ち上げた経験を持つオオバが開発初期にやれることを40個紹介していきたいと思います。
この記事を読むことで開発初期の時間の使い方が最適化され、中盤、後半の開発スピードに効いてきます。10本以上作ってきて思うのは、ゲーム開発は最初が肝心ということです。
最初の設計、ワークフローがどれだけ整えられているかが超重要。整っていないのに人を投入しても成果につながることはありません。
だからこそ暇している開発序盤こそ、成功するチャンスが有るということです。40Tipsと とても長い ですが自分のプロジェクトと照らし合わせながら集中して読んでいただければと思います。
ちなみにチーム開発前提のTipsですが、個人開発でも当てはまることは多いため、個人開発者の方もぜひ読んでみてください。
では本編に入っていきます。
👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!
- 初期設計編
- 1.開発環境と思想を決める
- 2.Unityプロジェクトディレクトリ構成を決める
- 3..gitignoreの設定をする
- 4.AndroidManifest.xmlの設定をする
- 5.コーディング規約を決める
- 6.MonoBehaviourクラスのAwake、Startメソッドは極力使わない
- 7.多人数で開発できるような設計
- 8.どのシーンからでも開発できるような仕組みの設計
- 9.サウンド再生基盤の開発
- 10.動画再生基盤の開発
- 11.ゲームエフェクトの再生と再利用機構の開発
- 12.ローカルファイル保存の仕組みを用意しておく
- 13.外部アセットを想定したロード処理を作る
- 14.Androidバックキー設計をする
- 15.ローカルPush通知の実装をしておく
- 16.最低限使用するであろうアセット導入
- 17.デバッグ環境の準備
- UI開発編
- 18.UI解像度を決める(UIを作り出す前に必ずやる)
- 19.共通UIパーツを共通のPrefabにする
- 20.文字列をソースコードやPrefabへの直書き回避とローカライズ対応
- 21.Unityのシーン遷移基盤開発
- 22.画面遷移システムの作成
- 23.ダイアログなどのシーンをまたいで使用するものはDontDestroyOnload領域へ
- 24.ダイアログシステム作成
- 23.UI用のCanvas共通化処理
- 26.UI階層構造のルールを決める
- 25.タップ・スワイプエフェクトを実装しておく
- 27.UI Environmentの設定
- 28.iPhoneXセーフエリア対応
- 29.UIカラー設定コンポーネントを作っておく
- 作業効率化
- ワークフロー系
- 34.ローカルで実機ビルドできる環境の整備
- 35.アプリ、アセットバンドルのビルド環境整備
- 36.サウンドアセット作成環境構築
- 37.動画アセット作成環境構築と検証
- 38.環境切り替えツールの導入
- 39.クラッシュレポートの導入
- 40.UIパーツのレギュレーションまとめページを作っておく
- 最後に
初期設計編
1.開発環境と思想を決める
最初にやるべきことは開発環境と開発思想を決めることです。開発環境について、次の2つが大きな影響を持ちます。
- ゲームエンジン
- ソースコードエディタ
本記事の読者はUnityエンジニアが多いため、ゲームエンジンUnity一択です。
ソースコードエディタは色々ありますよね。
- Rider
- VSCode
- Visual Studio
など。
これらの個人的なオススメと設定について解説します。
開発中は随時、リリース直前からはLTSごと
Unityエディタはバージョンが重要です。週一ペースでアップデートが入っています。アップデートを放置していると不具合の原因にもつながるため、アップデートは必要。
オオバは以下の基準でアップデートすることにしています。
- 開発中 : 節目節目でアップデート
- リリース直前から : 新しいLTSが出たらアップデート
Unityは日々進化しています。アップデートに対しての思想を決めておきましょう。
随時新しいUnityにアップデートするのが理想ですが、チームメンバー全員のUnityエディタを更新するのも手間ですし、事故も起きやすいです。開発の節目節目でアップデートするで問題ありません。
またリリースされたばかりの新しいUnityはバグが多いため注意です。
Unityエディタの新機能によって開発効率が上がることは珍しくありません。目玉機能がある場合は、検証した上でUnityエディタのアップデートをするのも手です。
しかし、ゲームのリリースから半年前からはアップデートは控えましょう。LTSごとのアップデートにしておいたほうが無難です。またUnityのアップデートにはUnity Hubを使えば簡単です。
LTSも出たばかりは不安定
オオバの経験上、Unityは出たばかりのLTSも不安定であることが多いです。
マイナーバージョンが6 くらいまで上がったらアップデートを検討するくらいの気持ちでいることをおすすめします。
ソースコードエディタはRiderが最もオススメ
ソースコードエディタの選定は悩みどころですが、現状Riderを採用しています。
- 自動フォーマットをでコードの共通化したい
- Unity開発をする上で機能が充実している
- ソフトとして安定している
Riderはオオバが求める条件を満たしているためです。コードの差分が出てくるため、基本的にチームメンバー全員がRiderを使うようにしています。
フォーマット設定はRiderデフォルト
- カスタマイズする時間がもったいない
- 人それぞれの好みを考慮が大変
- フォーマットの浸透と管理が大変
以上の理由からコードフォーマットの設定は Riderデフォルト状態 です。
注意点として Riderのバージョンによってデフォルト状態が異なる ためバージョンに注意です。揃えたほうがよいでしょう。
開発思想について
次に開発思想です。
オオバがよく採用するメインの思想は以下の2点です。
- Unityの機能を素直に使う
- 巨大なサードパーティフレームワークの使用禁止
時の経過でプロジェクトが破綻しないための対策です。具体的に解説していきます。
Unityの機能を素直に使う重要性
Unityのアップデートで死ぬ。Unityが勧めていない使い方をするとアップデートでトラブルが起きます。
- Obsoluteの機能の使用
- Previewパッケージの使用
- Unityが提供する機能を独自で作る
具体的には上記のような使い方です。どうしても特殊な使い方をしたい場合もあります。
そんな時は被害が最小限になるよう いつでも切り離せるような設計 を心がけましょう。
巨大なサードパーティフレームワークの使用禁止
オオバは巨大なサードパーティフレームワークの使用禁止することが多いです。理由は次の2つです。
- メンバーの学習コストアップ
- プロジェクトの生殺与奪を他人に依存
メンバーの学習コストアップ
新しいフレームワークを導入する際は正しい使い方の理解が必須です。
そして、正しい使い方をメンバーに伝え育成するコストはかなりのストレスを生みます。
もちろん育成コストがその後の開発スピードでペイできるなら良いですが。現実問題、 開発メンバーはコロコロ入れ替わることが多い です。
その度に育成するのはしんどいですよね。
まずそのフレームワークを知らないメンバーの育成から始まります。
プロジェクトの生殺与奪を他人に依存
プロジェクトの生殺与奪を他人に依存していないでしょうか。
ここ最近のゲーム開発は予算規模が大きく数億、数十億円の開発費を投資します。数十億円かけているプロジェクトに素性のわからない人がGitHubにアップしたフレームワークを採用していたりしないでしょうか。
もちろんソースコードを読んで大丈夫と判断したものなら大丈夫です。しかし大規模なライブラリとなると読もうにも読みきれません。オオバは技術選定をするときは必ず安全面、安定面を重視します。
- 法人が運営
- 導入実績
- 直近の更新頻度
- ノウハウの蓄積
以上のようなバックグラウンドを確認して技術を採用します。
「私が死んでも代わりはいるもの」
こういうフレームワークなら問題ないでしょう。代わりの誰かが意志を受けつぎ開発は継続されます。
フレームワーク導入時に大事なことは以下です。
- ただ流行りに乗らない
- 十分な時間をかけた検証する
話題になっているものってすごそうに感じます。
わかります。
しかし、そのプロジェクトで本当に求められていることを見つめましょう。それを実現する最短の道のりが新しいフレームワークの導入なのか。ただ、自分が使ってみたいだけなのか。
安定した枯れた技術のほうが良かった ということの方が多いですね。
2.Unityプロジェクトディレクトリ構成を決める
プロジェクト構成はUnity開発で揉めるがちポイントの1つです。
「好みが入るところに揉め事あり」
本章ではオオバはこうしているという事実をお送りし、お役に立てればと思っています。
まず 何をどこに格納するのか 方針だけ決めましょう。
最近採用する構成は以下です。
※Assetsフォルダ配下の構成です。
┌ AddressableModule/ ・・・サブモジュール
├ Addressables/・・・AssetBundleにビルドされるものを格納
└ Tools/・・・AssetBundleサブモジュール用のツール(主にアセットのチェッカー、ビューワー、非エンジニア向け機能)
├ Project/・・・アプリに含まれるアセット
├ Title/
└ (タイトルシーンのコンテンツが格納される)
├ OutGame/
├ Common/・・・OutGameの共通アセット
└ Screen/・・・各画面
├ Home/ ・・・ホーム画面ソースコード、prefab
├ Quest/ ・・・Quest画面ソースコード、prefab
└ Menu/
└ Dialog/・・・ダイアログ(ポップアップ)
├ Alert・・・アラートダイアログソースコード、prefab
└ Shop・・・ショップダイアログソースコード、prefab
├ Battle/
└ (バトルシーンのコンテンツが格納される)
├ Scenes/・・・シーン格納
└ Resources/ ・・・ Projectで唯一のResourcesフォルダ。
├ ExternalAssets/ ・・・外部アセット(アセットストアから落としたものとか)
├ Modules/・・・サブモジュール群
├ Preset/・・・プリセットデータ
├ ScriptTemplates/・・・スクリプトテンプレート
├ StreamingAssets/
├ Tools/・・・開発ツール
└ Sandbox/ ・・・テストコード格納
└ ohba_shunsuke/ ・・・各開発者ごとにディレクトリを切ったテストコード
無闇なResourcesフォルダはアプリ内のゴミを増やす
Resourcesは文字列からアセットを取得できる便利なフォルダですが、注意点が多いです。
というのもResources内のアセットはすべてビルド時に含まれてしまうからです。もちろんResources内が常に整理されているなら問題ありませんが、Resourcesフォルダが増えてくると整理しづらくなります。
だからこそResourcesフォルダは極力作らないほうが無難です。理想は1つで運用してリスクを減らすべきだと考えています。
アセットストアからダウンロードしたものをまとめる
アセットストアからダウンロードしたものは基本的にAssets配下に散らばり、Projectウィンドウの視認性を悪くしてしまいます。
そこで外部アセットは ExternalAssets
に移動しまとめることにしています。すると何が外部アセットで、何が自分たちが作ったアセットなのかがわかりやすくなるのです。
アセットの更新時には注意してください。
ソースコードとprefabを無理やり分けない
Unityのお作法として、次のようなフォルダ分けをよく見かけます。
フォルダ名 | 内容 |
---|---|
Scripts | ソースコードを格納 |
Prefabs | Prefabを格納 |
小規模のプロジェクトなら問題ないのですが、大規模なゲーム開発になると効率が悪くなります。というのもソースコードとPrefabはセットで扱いますが、ScriptとPrefabフォルダで分けてしまうと距離が離れてしまいます。
同じようなもの(機能単位のファイル)を近くに配置した方がProjectウィンドウの視認性も高まります。個人的にはソースコードとPrefabは同梱する形が好きです。
視認性が悪くなるためスクリプトとPrefabを別々に分けません。同じディレクトリに入れる事が多いです。機能単位でディレクトリを切ってそこにまとめるのが良いのです。
3..gitignoreの設定をする
.gitignoreとはgit管理する上で超重要なファイルです。git管理から外すものを.gitignoreに書くことで無駄なファイル更新を避けることができます。
過去に.gitignoreを設定していなかったプロジェクトにぶち当たった事があります。非常に大変でした。そして速攻.gitignoreを導入しました。
最初から.gitignoreは作成しておくことをおすすめします。
↑UnityであればGithubのテンプレートで存在します。そちらを使うとほぼ間違いないです。
4.AndroidManifest.xmlの設定をする
AndroidManifest.xml
はAndroid向け開発で必要です。ビルドの際に使われAndroidアプリの設定に使われます。
初期状態ではファイル自体存在しません。後々必要になるため用意しておきましょう。
配置場所はこちら Assets/Plugins/Android/AndroidManifest.xml
です。
ただ作るだけではなく必要最低限の設定を入れておきます。ゲーム開発でAndroidのマルチウィンドウに対応する事はほぼないため設定をオフにしておきましょう。
💻ソースコード : マルチウィンドウをオフにするサンプル
<?xml version="1.0" encoding="utf-8"?>
<manifest
~~~~ 略 ~~~
<application ~~~~ 略 ~~~ android:resizeableActivity="false">
~~~~ 略 ~~~
</application>
</manifest>
5.コーディング規約を決める
コーディング規約は揉めます。エンジニアが揉める第一候補です。メンバー間の宗教戦争に発展する場合もあり。地味に時間を取られてしまうため、解決方法を提案します。
Riderに任せる
Riderデフォルト設定のコーディング規約に準ずる。つまりRiderが指摘したら修正するということです。コーディング規約決定に時間を割くのはナンセンス。 規約にいくら時間をつかってもゲームは完成しません。
「Riderさんがそう言ってるから仕方ないよね♥」
前述の通りただしRiderのバージョンごとに微妙に異なるためバージョンを揃えることをオススメします。
6.MonoBehaviourクラスのAwake、Startメソッドは極力使わない
- Aawke
- OnEnable
- Start
- Update
などなど。Unityのライフサイクルイベントは基本使用禁止です。
- 実行順がわからない(保証されない)
- 処理の実行を検知しづらい
以上の理由から MonoBehaviourが提供するイベント関数は極力使わない ようにしています。
後から入ったメンバーも処理の流れを理解しやすいというメリットにも繋がります。
7.多人数で開発できるような設計
人数を集まれば開発速度が上がるという事はありません。正しく準備し、人を受け入れられる環境がなければ逆にマネージメントコストだけ増えて逆にスピードが落ちてしまうことなんてよくあります。
次の2点に注意することが重要です。
- 人を増やすタイミング
- 多人数で開発できる設計
1.人を増やすタイミング
増員タイミングのポイントは機能を量産できるフェーズかどうかという点です。
人員を投入して機能を量産できる状態であるならば開発速度の上昇が見込めます。逆に開発初期はお荷物になる可能性があるため注意です。
なぜなら開発初期は設計フェーズです。設計は基本的に少人数で行います。そして設計する人を増やしたところで 開発スピードは一切上がりません。
目安として設計が終わり、いくつか機能開発が進んで量産可能な状態になってからと考えておいた方が人件費を無駄に垂れ流さなくなると思います。
とはいえ投入する人のスケジュールやタイミングもあるためヒューマンマネージメントはめちゃくちゃ難しいです。
2.多人数で開発できる設計
またもう1つ重要なポイントは 多人数で開発できる設計になっているか? です。
- 機能同士が疎結合な実装になっているか
- Viewとロジックが別れているか
上記はプログラミングではよくある話です。密結合すぎて実装しづらい。Viewにロジックが記述してあって見通しが悪く不具合を出しやすいなど。
Unityの場合は次のようなポイントが個人的に気になります。
- GameObjectの構成
- Prefabの切り分け単位
- 必要UIコンポーネントの有無
- UIやサウンド、通信といった基盤機能の充実さ
など。多人数で開発するために用意することはたくさんあります。
例えば過去オオバが実際に出会った多人数開発できない状況を紹介します。
PrefabはUnity開発の基本です。Prefabを使いこなすことでチーム開発を円滑に進められます。しかし次のような開発現場がありました。
それはすべてのUIが1つのシーンに存在していたのです。画面、ダイアログ、ボタンに至る全てです。
最近のスマホゲームはリリース時に100画面を越えますから、100画面が1つのシーンに格納された状態です。
何が問題なのかというと 画面修正をするためにシーンファイルに変更を加えなければならない ということ。
ソースコードなら同じファイルの修正を行ってもマージ(結合)できますが、Unityの仕様的にシーンファイルはできません。
つまり画面に修正を加える場合、シーンファイルの変更が必要なため、100画面を100人で対応することはできず、1人で全て作業する必要があるということ。
お金を積んで解決できない状況なのです。
適切な単位でPrefab化
過去を後悔しても現実は変わりません。このときは適切な単位でPrefab化していき、ロード処理を追加。
この対応で最低限の多人数開発の担保は完了できました。
多人数開発はお金を積めばなんとかなるを実現するためのエンジニアの重要なミッションです。
多人数開発ができるかどうかの責任は初期メンバーのスキルにかかってきます。初期メンバーのエンジニアが将来のリスクを見越して多人数開発できる設計にしてくれるかどうかにかかっています。
もしこの記事を読んでいるあなたがゲームの初期設計者なのであれば、多人数開発できるのかどうかという点は強く意識しておくと良いです。
とりあえずよく使うGameObjectはPrefab化してきましょう。

【Unity】Prefabを生成する方法徹底解説
Prefabとは再利用可能なGameObject。Prefabは生成することで価値を発揮します。本記事ではPrefabの生成方法について徹底解説します。
8.どのシーンからでも開発できるような仕組みの設計
どのシーンからでも起動できるようにしておくと、開発の効率は上がります。それを実現するために、各シーンのエントリーポイントとなる共通クラスを継承したクラスをシーンのルートに配置しておくというルールを設けて実装しています。
例えば
- タイトルシーン
- アウトゲームシーン
- バトルシーン
という3シーン構成であればそれぞれにSceneEntry
クラスを継承したのコンポーネント
- TitleSceneEntry
- OutGameSceneEntry
- BattleSceneEntry
これらを各シーンのルートに配置します。
シーンエントリーポイントクラスの仕事とは?
- 通常起動とそれ以外の起動の処理における初期化処理の共通化
- クラス名の通り、シーンのエントリーポイント動かす ※そのために、Awake、Startをあえて使わないようにしてます
以下各シーン毎の起動例を紹介します。
タイトルシーンから起動した場合(通常起動)
- ユーザーが存在しなければ利用規約のダイアログを出す(ユーザーが存在すれば省略してログイン)
- 利用規約を許可したらユーザーを作成
- マスターデータの取得
- アセットのダウンロード
タイトルシーン以外から起動した場合(非通常起動)
- ユーザーが存在しなければ、利用規約など出さずにユーザー作成。存在すればログインする。
- マスターデータの取得
- アセットのダウンロード
という処理フローになり、通常起動と違って色々省略されています。これらの処理の分岐をシーンエントリーポイントクラスが担っており、このクラスを使う事でどのシーンからでも起動できるようにしています。
開発効率がとても良くなる ためオススメです。しっかり保守していきたいところです。
9.サウンド再生基盤の開発
ゲーム開発する上ではサウンド再生は必ず必要になります。開発序盤ではどんな技術を採用するかは決まらない可能性が高いです。
- Unity標準サウンド
- CRIなどのミドルウェア
など。
そこで何を採用しても大丈夫なように再生部分を以下のようなインターフェースにしておきます。
public interface ISoundPlayer
{
int Play(string soundName);
void Stop(int id);
void SetVolume(float volume);
void SetMute(bool isMute);
}
開発初期はUnity標準サウンドで実装しておいて、仕様が決まってきたら必要な技術に内部実装を置き換えていく想定です。
10.動画再生基盤の開発
動画を再生させる可能性がある場合は事前に再生検証をしておきたいです。前述したサウンド再生基盤動画版なので内容は割愛します(考え方は同じです)。
一点、ゲーム内設定のBGMボリュームを動画再生時に反映するというのを忘れやすいので注意です。
実機で再生できるかどうかの検証はもちろんですが動画は比較的ファイル容量が大きくなるためファイルをサーバーに置いてダウンロード時間の確認(実機で)を早めにしておくとよいでしょう。
11.ゲームエフェクトの再生と再利用機構の開発
バトル中に大量のゲームエフェクトが表示される事が想定される場合、エフェクトオブジェクトを再利用できる機構を事前に作っておくと良いです。
- 大量のエフェクトを毎度生成するとGCが発生しやすい
- Instantiateがそもそも処理的に重いため、スパイクの原因になる
ユーザー体感をより良くするためにできる限りエフェクトを再利用できるように設計しておきます。
またバトル開始前のローディング中にあらかじめ必要なエフェクトをロードする機能を追加しておくと良いでしょう。
12.ローカルファイル保存の仕組みを用意しておく
ローカルに保存するのはよくあるので事前に仕組みを用意しておく事ができます。
内部の実装は置き換えられるように一旦ラッパークラスを定義します。よく使いそうなメソッドを用意しておきます。
- SetInt
- SetFloat
- SetString
- SetBool
- GetInt
- GetFloat
- GetString
- GetBool
💻ソースコード : ローカル保存の例
LocalStorage.SetString("key", "HogeHoge");
var value = LocalStorage.GeString("key");
Debug.Log(value);// output : Hogehoge
13.外部アセットを想定したロード処理を作る
アプリ外部からアセットをダウンロードすることは今のスマホゲームでは必須機能です。
Unityが提供するアセットバンドルAddressable Asset System(以下:AAS)これらが該当します。
ただそれらを使うにしても機能を作らないといけません。
開発序盤にアセットシステムが無いまたは何を使用するかを決めていない場合もあると思います。
決まっていないからといって実装は後回しにするのはオススメしません。
ゲーム全体の作り直しのリスクが発生します。
そうならないような実装を最初から心がけたいところです。
インターフェースを利用して抽象化
public interface IAssetBundleManager
{
void Load(string assetBundleName, System.Action onComplete, System.Action onError = null);
void Release(string assetBundleName);
}
このような外部アセットのロードと解放を実装したインターフェースを定義しておきます。
開発序盤はResources.Load
で実装しておき後から実際のAssetBundleまたはAASに置き換えていくと良いかもしれません。
14.Androidバックキー設計をする
後に回すと面倒なのがAndroidバックキー対応です。バトル中やバトルのリザルトでは不要な場合がほとんどなので、Androidバックキーが必要になるのは主にアウトゲーム側です。
Androidバックキーを実行した時は以下の処理を想定して実装しておく
- ダイアログ表示中だったらダイアログを閉じる(閉じると不都合なダイアログが存在するので、分岐できるように設計しておく)
- 画面遷移システム側で履歴を保持して前の画面に戻る
- ホーム画面でバックキーが押されたらタイトルへ戻す(遷移履歴を消す)
- タイトルではアプリを終了する
Androidバックキーの連打対応
画面遷移演出中、API実行中などAndroidバックキーが動いては不都合な状態が存在するので、演出中、API実行中などAndroidバックキーが動いてはいけない状態をフラグとして取得できるようにして、trueだったらAndroidバックキーを押しても動かないようにしておきます。
15.ローカルPush通知の実装をしておく
ローカルPush通知もスマホゲーム開発なら必ず実装する機能なので先に手を付けておきます。以下のような要件が想定されます。
- アプリを終了した時、サスペンドした時にローカルPushを指定の時間後に予約する
- アプリを起動した時、ローカルPushの予約を全て消す
- 設定からON/OFFできる事が多いので、設定値を取得できるようにする
- Push通知の許可タイミングを任意のタイミングにできるようにしておく
サクッと無料で実装しておきたい場合はUnity公式のMobile Notifications
パッケージをPackage Managerからインストールできます。
16.最低限使用するであろうアセット導入
以下のアセットはどのようなプロダクトの開発でも必要な汎用性の高いアセットなので、初期から導入しています。
DOTween
DOTweenはスクリプトでアニメーション制御するための便利な老舗アセット。多くのタイトルで採用されています。オオバも長年お世話になっています。
SRDebugger
個人的にUnity最強のデバッグツールです。SRDebuggerがある、なしで大きく開発効率が変わってくるくらい重要なアセットです。
UniTask
Unityで非同期処理を実装するならUniTask一択です。以前はコルーチンが主流でしたが、async/awaitをUnityで使えるようになってからはUniTaskを使わない理由はありません。
UniWebview
UniWebViewも昔からお世話になっているアセットです。ゲーム開発中WebViewでお知らせや規約ページの実装をします。プラットフォームを吸収してWebViewを実装できるUniWebViewは非常に便利です。
Anti-Cheat Toolkit
Anti-Cheat Toolkitは数行でチート対策が可能なアセットです。あなたのゲームが悪意あるユーザーのクラッキングに悩まされているなら一度導入してみると良いかもしれません。
17.デバッグ環境の準備
前章で紹介しましたがSRDebuggerは最初から入れておいた方が良いです。
SRDebuggerはUnityエディタ、実機上ともにランタイム中のデバッグを超効率化するアセットです。AssetStoreから導入可能です。詳細は割愛しますが、これひとつでデバッグツールを全てまかなえるくらい汎用的な神ツールです。
オオバはSRDebuggerが好きすぎて新規プロジェクト開始時には必ず最初に導入しています。
そんなSRDebuggerファンのオオバが10年以上使用した経験を元に、体系的にSRDebuggerを学べる教科書的「を作成しました。デバッグが苦手な方はぜひ導入してみることをおすすめします。
UI開発編
18.UI解像度を決める(UIを作り出す前に必ずやる)
uGUIを使用する場合は、CanvasScalerに設定するReference Resolution
の値を決めるという話です。
デザイナーの元データにも影響があるので、UIを作り出す前に決めておく必要があります。
解像度毎のパターンを作り、対象となる実機何点かで実際に確認して決めれば良いと思います。
その際、スマホと解像度比率の大きく違うタブレット端末での見え方も注意すると良いでしょう。
19.共通UIパーツを共通のPrefabにする
UI画面にはよく各画面同じようなパーツが出てきます。
- 戻るボタン
- ダイアログに表示するOKやキャンセルボタン
- ゲージ
- 各種アイコン
などなど。
これらをそれぞれの画面で新規で作成するのは無駄なので、デザインがまだ仮の状態の時から共通のPrefabとして使い、デザインが仕上がってきたら、該当するPrefabの中身を差し替えていくのが良いでしょう。ただし、開発が進む中で無理やり使い続けている感が出てくる場合は、ケースバイケースで作り直した方が良いです。
20.文字列をソースコードやPrefabへの直書き回避とローカライズ対応
任意の文字列をソースコードやPrefab(Textコンポーネント等)に直書きすると、以下の状況で困ります。
- 文字列を一括置き換えができない
- 多言語対応(ローカライズ)する時に文字の使用箇所がわからない
そんな時は、キーを元に文字列を取得するヘルパークラスを用意すると良いです。
lang,JP,EN
yes,はい,YES
no,いいえ,NO
cancel,キャンセル,CANCEL
hp,HP,HP
上記のようなcsvを実行時にロードできるようにしておきます。
// 日本語をセット
Localization.SetLanguage("JP");
var str = Localization.Get("yes");
Debug.Log(str); // output : はい
このような感じでキーを引数にして文字列を取得するように実装しておくと文字列がソースコードに散らばらなくなって良いです。Localization.SetLanguage("EN");
とすれば機械的に英語に文字列が置き換わるようになるためローカライズ対応の手助けになるかもしれません。
21.Unityのシーン遷移基盤開発
ある程度大きなUnityプロジェクトになってくるとシーンを分ける事があります。分けた際に、そのシーン間を遷移させる仕組みを設計、実装しておくと良いです。
SceneManager.LoadSceneAsync("シーン名", LoadSceneMode.Single);
上記のUnity標準のSceneManager
使っても実現できます。しかしシーン間に演出、表現をはさみたい場合、機能不足です。
こういう場合はSceneManagerのラッパークラスを作って対応します。
どんな演出が考えられるか?
前述した通り演出が挟まるのであればその分の 余白 を残して実装する事が重要になります。
- Tips表示
- アセットローディングバーの表示
- 暗転させる
などなど。
それらを仕様が無いながらも他ゲーム、今までの経験を参考に拡張できるようなシーン遷移管理クラスを作っておくと楽になります。
22.画面遷移システムの作成
先程はシーン to シーン
の話でしたが今回は1つのシーン内での画面遷移についてです。
画面遷移は必ず必要になります。デザイン次第で大きく変わりますがとりあえず動くものを作っておきましょう。
// 全画面をEnumで定義する
public enum DisplayType
{
None = 0,
Home = 1,
Quest = 2,
Gacha = 3,
Menu = 4
}
画面をEnumで定義します。
上の画像のように、Enum値と画面prefabを紐付けておきます。
// 画面遷移開始
DisplayManger.Instance.Goto(DisplayType.Home);
上記のようなコードで画面が遷移するように実装しています。すごくざっくりな話になっていますが表示中の画面Prefabを指定したPrefabに入れ替える実装をしています。
23.ダイアログなどのシーンをまたいで使用するものはDontDestroyOnload領域へ
以下のようなシーン間、または各シーンで共通して使用したいもの、シーンをまたいで削除されたくないものはDontDestroyOnload(gameObject);
として、シーン遷移時にメモリから破棄されないようにします。
- ダイアログUI
- タップ・スワイプエフェクト
- ローディング、ダウンロード表示
- Tips表示
- UIのブロッキング(画面タップを無効化するオブジェクト)
24.ダイアログシステム作成
ダイアログは大抵どのようなゲームでも必要になるので、先に取り掛かります。
暫定要件
- ダイアログ以外の部分をタップしても、その後ろのコンテンツは反応しない
- ダイアログ以外の部分をタップすると、ダイアログを閉じる事ができる
- 細かい事だけど、ダイアログを開く・閉じる時にはSEが鳴るようにする
- ダイアログは重なって表示できるようにする
- OKボタン、キャンセルボタン押した時のコールバック設定
- OK、キャンセルの表示ON/OFF
などなど。
この中でも「ダイアログは重なって表示できるようにする」は、デザイン次第ではやりたくないという意見も出る場合がありますが、その時に考えて一旦動くものを作って体感を確認しながら進めるのがオオバは好きです。経験的にもその方がプロジェクトはより早く前に進みます。
// hogehogeとメッセージを表示させるダイアログを表示する
DialogManager.Instance.Open(new AlertDialog(){
message = "hogehoge",
okCallback = ()=> Debug.Log("OK"),
cancelCallback = ()=> Debug.Log("cancel")
});
上記のような感じでダイアログを呼べるように一旦実装しています。
23.UI用のCanvas共通化処理
UI用のCanvas、CanvasScalerの設定はプロジェクトで共通設定になる事が多いです。
それを毎度毎度設定するのは非効率のため、以下のような自動化できるコンポーネントを作っておきます。
using UnityEngine;
using UnityEngine.UI;
///
/// Canvas初期化
///
[ExecuteInEditMode]
[DisallowMultipleComponent]
public class UICanvasInitializer : MonoBehaviour
{
private CanvasScaler _scaler;
void OnEnable()
{
Execute();
}
#if UNITY_EDITOR
void OnValidate()
{
Execute();
}
#endif
void Reset()
{
Execute();
}
void Execute()
{
if (_scaler == null)
{
_scaler = GetComponent();
}
// 内容は適宜
_scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
_scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
_scaler.referenceResolution = new Vector2(1920f, 1080f);
}
}
このような共通コンポーネントを作っておくと、修正が入った時に対応しやすいです。
26.UI階層構造のルールを決める
デザインによって大きく変わる可能性がありますが、大抵以下のような構成になるので一旦これで作ってしまいます。
各シーン
- 最背面レイヤー・・・背景
- コンテンツレイヤー・・・各シーンのコンテンツ
DontDestroyOnLoad領域
- 通常ダイアログレイヤー・・・通常ダイアログ
- オーバーレイレイヤー・・・ローディング、Tipsなど
- システムダイアログレイヤー・・・システム系ダイアログ
- 最前面レイヤー・・・・タッエフェクトなど
25.タップ・スワイプエフェクトを実装しておく
スマホゲームを作る場合、必ずと言っていいほどタップした時やスワイプした時のエフェクトが必要になります。
優先度的には後でもよい判断をされるかもしれませんが、先に実装しておく事をおすすめします。
タップ・スワイプエフェクトは最前面に表示されなくてはいけません。
後から実装すると、UIの階層関係を構築する際に見落としてしまって、手戻りをしてしまう可能性があります。
オオバは表示階層に関わるものに関してはできるだけ優先的に実装しておく事にしています。
また、先に実装し、prefab化しておけば、クリエーターにブラッシュアップをお願いするのも楽です。
27.UI Environmentの設定
Prefab Editing Environmentsは、Unity2018.3からNestedPrefabが導入され追加された設定です。
必ず設定しておいたほうが良いのは UI Environment
です。
uGUI関連のPrefabをプレファブモードで編集する際、uGUIはCanvas配下に存在しないと表示が崩れます。
UI EnvironmentにCanvasやカメラを配置したシーンを設定しておくとプレファブモード時にそのシーンを使用してくれます。
NestedPrefabを使用する際は必須設定なので序盤に忘れないように設定しておきたいです。
ちなみに、UI Environmentに設定するシーン内の以前の章で紹介したCanvas設定を適用すると良いです。
28.iPhoneXセーフエリア対応
セーフエリア対応はデザインの序盤に思想を決めて動けていないと、後々大きな手戻りが発生する可能性があります。
デザイナーとしっかり相談して、意志を統一していきたいところです。
また、iPhoneX系の実機で日々確認するのも大事です。
29.UIカラー設定コンポーネントを作っておく
デザインが進んでいくとキーとなるカラーが決まってきます。
uGUIのパーツを予め白色で作成しておき、プログラムで色を重ねて作成する場合があります。
その際、指定カラーをUnity上でひとつひとつセットしていくのはとても無駄な作業です。
少しでも楽をするための以下のようなコンポーネントを用意しておきます。
///
/// 決まったカラーをセットする
///
public class GraphicColorSetter : MonoBehaviour
{
[SerializeField] private ColorType _colorType;
[SerializeField] private Graphic _graphic;
// trueにすると実行時に指定色を反映する
[SerializeField] private bool _isRuntimeApply;
void OnEnable()
{
if (isRuntimeApply)
ApplyColor();
}
public void SetColorType(ColorType type)
{
_colorType = type;
ApplyColor();
}
void ApplyColor()
{
// ColorResolverにColorTypeに対する色を定義して返却できるようにしておく
_graphic.color = ColorResolver.Resolve(_colorType);
}
#if UNITY_EDITOR
void OnValidate()
{
if (Application.isPlaying == false)
{
if (_graphic == null)
{
_graphic = GetComponent();
}
else
{
ApplyColor();
}
if (_graphic == null)
{
Debug.LogError("Graphic is not Found", this);
}
}
}
#endif
}
このようにプルダウンでカラーを指定し反映する事ができるので効率的ですし、非エンジニアでも対応可能になります。
また開発序盤中盤はカラーの変更はザラにありますが、その反映もソースコードを変更するだけで対応できるのもメリットです。
作業効率化
30.よく使う拡張メソッドを用意しておく
- Transform
- RectTransform
- List
- String
- Dictionary
- Component
- GameObject
これらよく使うクラスのよく使う処理は、拡張メソッドとして用意しておくと開発効率が上がります。
using UnityEngine;
namespace Hoge.Extensions
{
public static class GameObjectExtensions
{
///
/// 存在しなかった場合はAddComponentする
///
public static T GetOrAddComponent(this GameObject target) where T : Component
{
var comp = target.GetComponent();
if (comp == null)
{
comp = target.AddComponent();
}
return comp;
}
}
}
※GameObjectの拡張メソッド例
拡張メソッドの注意点
拡張メソッドを使用しているのかどうかがパッと見、分かりづらくなるためネームスペースにExtensions
をつけておく事をオススメします。
先の例でいうとnamespace Hoge.Extensions
の部分です。
31.よく使いそうなシェーダーを用意しておく
乗算、加算(カラー加算、加算ブレンドの両方)、ブラーシェーダー等を用意しておくと良いと思います。
※ググれば出てくるので詳細は割愛します
32.テクスチャインポータの作成
ゲームを作っていると様々な画像アセットが必要になります。ターゲットプラットフォームごとに指定する圧縮テクスチャの種類やクオリティが変わってきます。
これらを毎度設定するのはオペミスに繋がりますし、ミスをしてても気づきづらいため、AssetPostprocessorを使って所定のディレクトリに格納したら、自動でインポータが実行されるようにしておくと良いです。
33.アセットバンドル名を自動で設定されるようにする
======【注意】本章は古くなっているためリライト中です======
アセットバンドルを利用する場合は、参照用のアセットバンドル名を必ず付ける必要があります。
┌ AddressableModule/ ・・・サブモジュール
├ AssetBundles/・・・AssetBundleにビルドされるものを格納
Resources/
├ chara
├ hoge
├ foo
AssetBundlesディレクトリ
配下に格納すると、AssetPostprocessorで自動でアセットバンドル名が付与されるようにしています。例えばhogeディレクトリにtest.prefab
を格納すると、 chara/hoge/test
というアセットバンドル名に自動で追加されます。
アセットバンドル名
とResources.Loadのパス
を共通化するためにResourcesフォルダ名を抜いたパス名にしています
ワークフロー系
34.ローカルで実機ビルドできる環境の整備
自分のPCで実機ビルドできるようにしておくことは非常に重要です。理由は2つ。
- パフォーマンスチューニングする上で必須
- 実機のみで起きる不具合の調査がしやすい
パフォーマンスはゲーム開発で非常に重要です。どうしても機能や演出を盛り込んでパフォーマンスが悪くなるときがありますが、チューニングを通してクオリティを担保していきます。
チューニングしやすい環境づくりがとても大事。自分のPCでビルドできるように準備しておくとチューニングしやすいです。
特にXcodeを使ったチューニングは強力なので、iOS実機で実機ビルドできるようにしておくことをおすすめします。
もう1点が実機のみで発生する不具合調査です。Unityエディタ上では起きないのに実機で発生する不具合は調査が大変です。手元でビルドできるようにしてバグ修正の時間短縮につなげていきましょう。
35.アプリ、アセットバンドルのビルド環境整備
アプリ、アセットバンドルのビルド環境は必ず必要になります。ジェンキンスを使ったビルドジョブを作り、終了したらSlackに通知するようにしています。
アプリはビルドされたら自動でFirebaseやDeployGateなどのWebサービスにアップロードされるようにしておきましょう。
開発メンバーがそれぞれ実機にダウンロードできる環境を作っておくと開発効率も上がりますし、不具合の発見にも繋がります。
またビルドされたアプリはビルド番号をアプリ名に入れておくと便利です。
イメージこのような感じ。
36.サウンドアセット作成環境構築
Unity標準サウンド以外を使用する事が最初から決まっている場合は、サウンドアセット作成のワークフロー構築に早めに取り組みたいです。今回はCRIサウンドを使用すると仮定します。
※Unity標準サウンドを使用する場合は不要
CRIサウンドを利用する場合は、オーディオファイルをCRI専用ファイルに変換しなければなりません。
変換処理にAtomCraftを利用する場合、そのワークフローを事前に検証、環境構築しておくと良いです。
また、大人数でAtomCraftを使用する場合、どのファイルをgitignoreに入れなければならないかなど、時間に比較的余裕のある開発序盤に潰しておくと時間を効率に使えます。
37.動画アセット作成環境構築と検証
動画はエンコードの仕方で大きくクオリティが変わってきます。また動画が正しく再生するのか事前に検証しておくことをおすすめします。
- iOSでは再生できたがAndroidでは再生に失敗した
- Androidの特定の端末で再生できなかった
- アルファチャンネルを含んだ動画が再生できなかった
などなど。
Unity標準で再生させる場合はVideoPlayerを使いますが、よくよく動画の再生検証をしておきましょう。オオバの経験上、Androidでの再生が怪しいです。
アセットで解決するならAVPro Videoが有名です。VideoPlayerでどうにもならないときは試してみると良いでしょう。
ミドルウェアで解決するならCRIWAREです。CRI Sofdecを使うことで安定した動画再生が可能となります(ただし高額です)。
何はともあれ、動画を採用することが決まっているのであれば暇なUnityエンジニアはとにかく動作検証に時間を使うと良いです。暇するよりはとても有意義な時間の使い方と言えます。
38.環境切り替えツールの導入
ゲームを開発する上で最低限以下の2種類は切り替えます。
- 開発環境
- リリース環境
その他にもステージング環境、サンドボックス課金環境などプロジェクトによっては様々な環境が必要になります。
環境を切り替えた時には以下の情報を切り替えています。
- 接続先URL
- アプリ名
- アプリID
- 使用シンボル
public string ApiBaseUrl =>
#if DEV
"https://dev.sample.com/api/";
#elif RELEASE
"https://sample.com/api/";
#elif LOCAL
"https://localhost:8080/api/";
#else
"https://dev.sample.com/api/";
#endif
※環境毎のAPI接続先切り替えの例です。
これらの情報を切り替えられるようなツールを作っておくと後々楽です。
39.クラッシュレポートの導入
クラッシュレポートとはアプリがクラッシュした際のレポートです。開発を進めていくとふとしたタイミングから実機でクラッシュするようになることがあります。
何が原因なのか、ログを仕込もうにもクラッシュしてしまうためログを確認できません。そんなときにクラッシュレポートです。クラッシュレポートから不具合の原因を探ることができます。
だからこそ、クラッシュレポートは開発序盤から入れておくことをおすすめします。開発序盤はコードを大きく書き換えることも多くバグも起きやすいためです。
とりあえず無料で使えるFirebaseのCrashlyticsを導入しておくとよいでしょう。
40.UIパーツのレギュレーションまとめページを作っておく
UIパーツの命名ルールはエンジニアリングを知っている人が決めるべきだとオオバは思っています。いわゆるTA的な人です。
オオバはTA的な動き方をする事が多いため皆が見れる場所にUIパーツのレギュレーションページを作っておきます。
過去にConfluenceやNotionなどを利用してきました。
現時点ではNotionが使いやすい印象です。Notionを使って最初にドキュメントのひな形を作っておくとメンバーは迷いません。人が増える前にワークフローを構築しておく事が大事。
- 画像サイズ
- ファイル命名ルール ※例 :
キャラID_icon.png
- 格納フォルダパス
- サンプル画像
以上の情報を1ページにまとめ、変更が入る度に更新しています。特に開発序盤は更新頻度が多いため、ある程度プロジェクトが落ち着いてからでも問題ありません。

最後に
ここまで読んでいただきありがとございます。40のTipsは流石に長かったかもしれません。
最も言いたいことは 「暇な時間はない」 ということ。
何を作るのか一切存在しない状態ならしょうがないですが、何かゲームの断片情報があるならそこからやるべきことが広がっていきます。
今回汎用性の高いものだけを紹介しましたが、関わるプロダクトの種類によってはまだまだやる事は変わってきますし、優先順位も変わります。
今回紹介した大小含めた40のTipsが皆様の開発のお役に立てれば幸いです。

筆者のXをフォローしよう
「Unity初心者大学」というUnity初心者向けのYouTube始めました!!
ぜひチャンネル登録をお願いします!
最後まで読んでいただきありがとうございました!
すばらしいUnityライフをお過ごしください。