こんにちは、Unityエンジニアのオオバです。

お悩みさん
お悩みさん
  • Unity開発で気をつけることって何?
  • Unity開発で当たり前のことを知りたい
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    オオバはUnityを触りだして早11年。Unityバージョン3の頃から仕事で使っています。 Unity開発は気をつけるところだらけ です。ちょっとした油断や無知が大きなトラブルを生むことも。

    そういう情報は 先に知りたい ですよね。今回は Unity初心者向けにUnity開発で気をつけるべき11のポイント を紹介します。この11のポイントは 初心者はとても陥りやすい ため、ぜひ最後まで読んでみてください。

    では早速紹介していきます。

    👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

    1. Unity標準ボタンの使用禁止

    いきなりビックリかもしれませんが、 Unityが提供する標準UIボタンは使用禁止 です。

    標準ボタンとは メニューGameObject > UI > Button から作れるおなじみのボタンです。

    初心者が気をつけるべきUnity開発11のポイント_0

    オオバはカジュゲーのようなライトなゲームでも使用しません。簡単なツール開発くらいなら使うかもしれませんがそれくらい 慎重 です。

    理由は 「拡張性がない」「結局独自ボタンに置き換える必要が出てくる」 からです。

    詳しい解説は次の記事を参考にしてみてください。11年Unity開発してきましたが、一度たりとも標準ボタンで世の中に無事にリリースできたことはありません。

    2. シリアライズする変数にpublic禁止

    シリアライズする変数をpublicは禁止にしましょう。言葉だけではすこし分かりづらいため、ソースコードで解説します。

    public class Test : MonoBehaviour  
    {
        // × オオバはこの方法を禁止しています  
        public Transform shibuya;  
    
        // ○ こちらを採用  
        [Serializefield] private Transform hototogisu;  
    }
    

    シリアライズとは「Prefabやシーンに対してデータを保存すること」です。Unityではpublicまたは [SerializeField] を変数に付けることでUnityオブジェクトをシリアライズできます。

    シリアライズする際は、publicではなく、 [Serializefield] をセットし、 private 変数にするのが安全です。理由は、 インスタンス外から簡単に上書きできてしまうから です。

    Test _test;  
    
    void Start()  
    {
        // 上書き可能 => 危険  
        _test.shibuya = null;  
    
        // 上書きできない => 安全  
        _test.hototogisu = null;  
    }
    

    このようにクラスの外側から値を更新できてしまうのです。シリアライズするものはたいてい後から変更したくないものです。また、 シリアライズしたものが後から上書きされることを想定しません。

    シリアライズした↑これらのデータを後から上書きしてしまうことはレアケースです。混乱や不具合を避けるために シリアライズ変数にpublicは禁止 しましょう。

    👉 【Unityの基本】Transformを徹底解説「移動」や「回転」だけじゃない

    3.カメラの同時使用数は極力減らす

    カメラの同時使用数は極力減らすようにしましょう。正直 カメラの負荷は大きい です。

    Unity Profilerで見ても一目瞭然。3Dのゲームであれば 3D表示用2DUI表示用 の2つ使います。しかし気を抜いているとどんどん増えていくのがカメラ。

    などなど。

    別に増えること自体が悪とは言いません。

    ※限度はあります

    同時に使用するカメラの個数を制限する設計が大事 なのです。カメラの同時使用数がとんでもない負荷を生み出し、ゲームの体験を損ないます。また カメラを後から減らすことは意外と大変 です。なぜなら見た目に関わるため、目視でチェックする必要があり調整に時間がかかるからです。

    以上のことから 序盤からできる限りカメラを減らすということを心がけるとよい です。

    4.コンソールは色分けして見やすくする

    開発中、大量のログがコンソールに出力されます。ログはプログラムの状態を簡単に知らせてくれる大事な要素。だからこそ見やすいコンソールが開発には役立ちます。そこで、 コンソールに色付け してみましょう。

    Unityでは簡単にログに色を付けることができます。

    Debug.Log ("<color=yellow>黄色のログ</color>");  
    Debug.Log ("<color=#0000ff>青色のログ</color>");  
    

    初心者が気をつけるべきUnity開発11のポイント_1

    このように <color=色名 or カラーコード></color> タグをログに仕込むことでコンソールをカラーリング可能です。

    例えば、 「通信系の処理はピンク」、「ゲームループ処理は黄色」「バトルは緑色」といった、各機能でログの色を分けると処理の内容や流れを理解しやすくなるためおすすめです。

    5. 検索しやすいログ出力にする

    ログ関連が続きますが、出力ルールを設けましょう。繰り返しになりますが、 ログはデバッグする上で欠かせない存在 です。先ほどのログのカラーリングに加えて検索しやすいログにすることをおすすめします。

    具体的にはこんな感じです。

    Debug.Log ("【API】通信開始");  
    
    //~~~~ 略 ~~~~  
    Debug.Log ("【API】通信完了");  
    

    このように通信関連の処理だったら 【API】 という文字を追加するのです。

    これがどんな意味を持つかといいますと 「ログの検索」に効果を発揮します。

    Unity2020からコンソールに ログの検索機能 が実装されました。今まで外部アセットに頼ってきたことをデフォルト状態で使用可能なのです。

    初心者が気をつけるべきUnity開発11のポイント_2

    このような感じで検索できるためかなり便利です。

    ログは放っておくと大量に出力されてしまいます。重要なログも気づかず流れてしまうため、検索にヒットする工夫をすると開発効率はアップします。ぜひログのカラーリングとあわせて活用してみてください。

    6.Find系メソッドは極力使わない

    Unityにはオブジェクトを探す関数がいくつか提供されています。結論からいうと、 特別な理由がない限り極力使うのは禁止 にします。それぞれのケースで解説していきます。

    TransformのFindメソッド

    Transformの Find メソッドは子階層のオブジェクトを取得可能。例えば次のようなHierarchyウィンドウ。

    初心者が気をつけるべきUnity開発11のポイント_3

    Grandchild をFindメソッドで取得すると以下のようなコードになります。

    // パスを指定して取得  
    var grandChild = transform.Find ("Parent/Child/Grandchild");  
    

    一見便利そうですよね。

    しかし実際のゲーム開発の現場では2つの問題点があるのです。

    TransformのFindメソッドの問題点

    ①仕様変更にもろい

    ②プログラムの理解に時間がかかる

    TransformのFindを使うと 仕様変更にかなり弱い です。
    なぜならオブジェクトの参照をパス指定しているため、GameObjectの階層が変わった途端にソースコードも変更する必要があるからです。ソースコードに変更が入るということは テスト工数も上がります。 しかもゲーム開発中はデザインは 頻繁 に変わりますよね。

    そんな環境下でパス指定は時間を溶かす行為。 絶対におすすめしません。

    そして プログラムの理解に時間がかかります。 ソースコードに書かれた指定パスを覚え、Unityエディタに戻りパスを照らし合わせながらオブジェクトを探します。オブジェクトを探すだけでとても大変なのです。

    解決方法は 事前のシリアライズ です。詳しい内容はこちらの記事にまとめていますので興味ある方は読んでみてください。

    GameObjectクラスのFind系メソッド

    GameObjectくらいには4つのFind系関数があります。Transformと同様基本的には 禁止 です。

    こちらのGameObjectのFind系関数もTransformと同様、文字列指定でGameObjectを検索します。
    前述のTransformのFindと重複しますが、 GameObject名は開発中とても変更が入ります。

    その度に「ソースコードを更新してテストする」という 非効率な状態へ 。Find系メソッドはよほど理由がない限りは 使用は禁止 しましょう。

    Object、ResourcesのFind系関数

    Unityオブジェクトの基本クラス、ObjectにもFind関数が存在します。

    Hierarchyウィンドウのコンポーネントを取得できる便利な関数です。文字列指定ではないため、 タイプミスなどは起きづらくまだ使えます。

    しかし 「Hierarchyウィンドウ全てを検索する」 という 非常に重い処理 です。 あまり頻繁に使うものではない ということを覚えておいてください。

    👆このような場面で登場します。もし使用する場合は一度取得したら保持して 再利用 するなどの工夫をしましょう。

    7.Prefabとコンポーネント名は同名にする

    Prefabとコンポーネント名はできる限り同名にすることをおすすめします。Hierarchyウィンドウを眺めて、お目当てのコンポーネントがどこにあるのかわからなくなる ときありませんか。

    回避策としてコンポーネントを追加した Prefab、GameObjectの名前をコンポーネントと同名にする というアイデアです。コンポーネントとPrefabが同名であれば、探す手間がかなり減ります。

    ただし、1つのGameObjectに対して複数コンポーネントがセットされますよね。だからできる限りで大丈夫です。主要コンポーネントの名前をつけてもらうだけでOKです。それだけでだいぶ見通しが良くなります。

    PrefabはUnity開発でとても強力な機能です。必ず身につけておきたいスキルの1つ。もしPrefabの理解に自信がない方はこちらの記事がおすすめです。 Prefabの理解とともに使い方まで徹底解説 しています。

    【小ネタ】Hierarchyウィンドウからコンポーネントを検索可能

    少し脇道にそれますが、Hierarchyウィンドウの検索窓には小技があります。

    初心者が気をつけるべきUnity開発11のポイント_4

    「t:コンポーネント名」 と入力すると指定したコンポーネントがセットされたGameObjectがヒットします。Prefabにどんなコンポーネントがアタッチされているかわからないときにあわせて使ってみてください。

    8.SendMessageは使用禁止

    SendMessageとは 文字列でメソッドを呼ぶ機能 です。使い方次第ではとても便利なメソッドですが、ルールが定まっていないとカオスになります。

    SendMessageは引数に文字列で実行したいメソッド名を渡します。

    void Start()  
    {
        // SendMessageを使ってTestFuncメソッドを呼ぶ  
        SendMessage ("TestFunc");  
    }
    
    void TestFunc()  
    {
        // 処理  
    }
    

    メソッド名を 文字列 を渡していることが厄介なのです。指定した TestFunc メソッドがどこから呼ばれているかパッと見わかりません。

    呼び出し元にたどり着くのが非常に大変です。つまりソースコードを読む難易度が一気に跳ね上がるのです。具体的には以下の方法でSendMessageの呼び出しを検索します。

    1. 「SendMessage」を _全文検索
    2. TestFuncを使っているか箇所を調べる

    SendMessageが1つならまだしも、大量に使っていたらなおさらで、取り返しがつきません。

    わざわざSendMessageを使うのであれば、 TestFunc メソッドを持つインスタンスの参照を予め取得したほうが効率的です。

    特に チーム開発では要注意 です。ルール化を徹底しておかないと大事故になる案件。オオバの場合、SendMessageはよっぽどのことが無い限り 使用禁止 です。

    9.Updateメソッド内でLINQは禁止

    LINQはとても便利です。ただし Updateメソッド内でLINQは禁止 しましょう。

    LINQとは配列などのコレクションを扱いやすくした機能群です。負荷が高くなりがちな点が問題 になります。

    Unityには「Awake、Start、Update、OnEnable」といった特殊なメソッドが用意されています。その中でUpdate。Updateとは、Startメソッド実行後、 毎フレーム実行 されるメソッドです。

    毎フレーム実行するUpdate内で LINQは使用禁止 です。理由は2点あります。

    Update内でLINQが使用禁止の理由

    ①ゲーム中の負荷が無駄に上がってしまうから

    ②カクツキの原因になってしまうから

    ①ゲーム中の負荷が無駄に上がってしまうため

    前述の通りLINQは負荷が高いです。その負荷の高いLINQを毎フレーム実行するとゲーム全体が重くなってしまうのです。

    解決策としては for文に書き換え です 。どうしてもLINQよりコード量が増えますが、パフォーマンスと天秤にかけて判断してましょう。もちろん パフォーマンス計測で問題なければ大丈夫です。

    ②LINQがカクツキの原因になってしまうから

    LINQを使用すると ゴミが発生 します。

    ※専門用語ではメモリアロケーション

    毎フレームLINQを実行することで大量のゴミが発生します。ゴミが一定数超えると、掃除が始まります。掃除のことを GC(ガベージコレクション) と呼びます。

    この GC がゲーム中のカクつきの原因になるのです。やはりゲームはスムーズに動く方が良いですよね。以上の理由から、 Update中にLINQは使用禁止 なのです。

    Updateのほかに LateUpdate というメソッドもUnityには用意されています。似ているようで全く違います。Updateについて知識を深めたい方はこちらの記事がおすすめです。

    10.Resourcesフォルダの使用は最低限にする

    Unityには特殊なフォルダが存在します。その1つが Resources です。

    Resourcesフォルダには注意点が1つあります。 Resourcesにファイルを入れすぎるとアプリ起動が遅くなる のです。ゲーム開発では 致命的 ですよね。

    つまり、 Resourcesフォルダに入れるものは最低限 にしましょう。

    そもそもResourcesとは 文字列からオブジェクトを取得できる便利なフォルダ です。
    Unityの初期から実装されて、今なお現役の機能。

    // パス指定でオブジェクトを取得  
    var questPrefab = Resources.Load<GameObject>("OutGame/Quest");  
    

    使い方は簡単でResourcesフォルダ内のオブジェクトは、👆このようなソースコードで取得できます。ご覧の通りResourcesはとても便利なフォルダであるため 多用しがち です。

    しかしアプリの起動を遅くしてしまうため、本当は存在しない方が良いです。 Resourcesフォルダは使うとしても最低限の使用に留めましょう。

    11.デザイナーとできる事とできない事の認識を合わせておく

    チーム開発の話ですが、 他職種メンバーとUnityで実現できる事とできない事の認識合わせ は超重要です。今回はデザイナーとのやり取りを例に解説します。

    例えば以下のような内容です。

    などなど。制作するゲームの仕様に大きく関わることです。

    👉 【Unity UI】uGUIできれいなソフトマスクを作る方法

    開発進行中は 随時デザイナーと表現方法を密接にすり合わせておく必要があります 。なぜならプロジェクト後半に以下のようなトラブルが起きるからです。

    このような悲惨な事件です。 チームメンバーが出来る限り納得できる状態で開発を進めたい ですよね。そのためには Unityエンジニアは多職種との認識合わせを綿密に行う必要がある のです。コミュニケーションはとても大事です。

    👉 【Unity】知っておくべきUIテキストの文字間(カーニング)事情

    こちらの記事では Unityの標準機能では難しいUI表現 をまとめています。ゲーム開発序盤のスケジュールや見積もりの精度を上げるためにもぜひ、一読してみてください。デザイナーとエンジニアの連携はゲームのクオリティに大きく関わります。

    初心者が気をつけるべきUnity開発11のポイントまとめ

    この記事は初心者が気をつけるべきUnity開発11のポイントを解説しました。最後に内容を簡単にまとめます。

    Unity開発で気をつけたい11のポイント

    ①Unity標準ボタンの使用禁止

    ②シリアライズする変数にpublic禁止

    ③カメラの同時使用数は極力減らす

    ④コンソールは色分けすると便利

    ⑤検索しやすいログ出力にする

    ⑥Find系メソッドは極力使わない

    ⑦Prefabとコンポーネント名は同名にする

    ⑧SendMessageは使用禁止

    ⑨Updateメソッド内でLINQは禁止

    ⑩Resourcesフォルダには最低限のものを入れる

    ⑪デザイナーとできる事とできない事の認識を合わせておく

    どれも 開発初期から意識しておきたい ものばかりです。開発途中から対応しようとすると、作り直しも発生します。

    開発が始まったときこそ、 ルールづくり が大事になります。もちろん最初から完璧なルールはできません。走りながら修正していくスタイルがおすすめです。大事なことは ゲームづくりに集中できる環境づくり です。ゲームづくり以外のことに時間を割くのはナンセンス。

    ぜひ今回紹介した11点を取り入れて、 効率的な開発環境 をつくってみてください。

    この記事があなたのゲーム開発に少しでもお役に立てたら嬉しいです。

    「Unity初心者大学」というUnity初心者向けのYouTube始めました!!
    ぜひチャンネル登録をお願いします!

    最後まで読んでいただきありがとうございました!
    すばらしいUnityライフをお過ごしください。

    オススメ記事
    検証環境