Edited at
UnityDay 13

Unityで各種定数を定義して使う

More than 3 years have passed since last update.


はじめに

こちらはUnity Advent Calendar 2015の13日目の記事です。

その2もあるので合わせて見てみるといいでしょう。


概要

次のコードを見てください。

Application.LoadLevel("Title");

このTitleという文字列。

シーンファイル(.unity)に紐付いているのですが、いかにもtypoしそうですよね。

こちらについて定数で管理できればtypoしてしまってもコンパイル時にわかりますし、コードの補完も効きます。

また、変更があっても検出が楽にできますし、いいことずくめです!

更に今回は、手動での管理ではなく自動でコードの生成を行うことにより、ミスをできるかぎり少なくしたいと思います。


何番煎じだよ

コガネブログさんがぶっちゃけ全て書いていますのでそちらも合わせてご参考にしていただけたらと思います。

(リンク貼って紹介することがまずければご一報ください)

* 【Unity】シーン名を定数で管理するクラスを生成する拡張機能

* 【Unity】タグ名を定数で管理するクラスを生成する拡張機能

* 【Unity】レイヤー名を定数で管理するクラスを生成する拡張機能


ということで

それを実現する手順を早速見ていきましょう。


手順


概要


シーン名等々の定数について取得する方法を調べる

例:シーン名

* Unityのシーン一覧を取得する


定数定義をするクラスを記述するファイルを自動生成するクラスを書く

各種定数の取得方法のほとんど全てがusing UnityEditor環境が必要になると思います。

であるため、このクラスはEditorディレクトリ以下に配置すると良いでしょう。(理由は割愛)



  • MenuItem属性を付けたメソッドを定義する


    • このタイミングで、PostProcessBuildDidReloadScripts属性を付けると

      出力ファイルに問題があった場合にややこしいことになる印象があるので(私だけ?)、

      最後につけるのがいいと思います。

    [MenuItem(my_tool/generate/scene)]
    
    GenerateScene()



  • 先に調べた方法で定数を取得し、定数定義をするクラスをファイルとして出力


    • ただのテキスト出力なので割愛

    • ただし、定数名として使用できない文字の扱いについて対応する必要があります。




  • メニューから上記メソッドを実行し、ファイルを出力、出力内容のチェックを行う


    • コンパイルエラーになる場合は出力されたファイルの内容を全消去し、

      自動生成クラスを修正して再度ファイルの出力をしましょう。




  • PostProcessBuildDidReloadScripts属性を付ける


    • これにより、定数の定義が変わった場合にビルドが2回走りますが

      (古い状態の定義ファイルでのビルド -> 定義ファイル出力 -> 新しい定義ファイルでのビルド)

      毎回そうなるというわけではない(ファイルの内容に変更がなければビルドされない)ので問題ないと思います。




実際のコードで使用する

割愛


まとめ

これでUnityによくある定数が文字列(or数値)という問題に対応できます!


巻末付録

主要な定数系のデータの取得方法をメモしておきます。

コメントをいただければ追加します。


シーン名

EditorBuildSettings.scenes


タグ名

InternalEditorUtility.tags


レイヤー名

InternalEditorUtility.layers


ソーティングレイヤー名

var tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);

var sortingLayer = tagManager.FindProperty("m_SortingLayers");
for (int i = 0; i < sortingLayer.arraySize; ++i)
{
string tag = sortingLayer.GetArrayElementAtIndex(i).displayName;
...
}