Monthly Archives: 8月 2015

[Unity] インスペクタから定数シンボルを設定できるようにする

Unityに関するメモ書きです。

Unityのインスペクタ上で値を設定する上で不便に感じていたことがあります。
例えば、以下のように2つのクラス意味のある値(マジックナンバー)を設定することを考えてみます。

2つのクラスで使用するwidth、heightは同じ値である必要があるとします。
このようにスクリプト上でマジックナンバーを設定する場合、次のように定数シンボルを用いるのが一般的でしょう。

これはスクリプトに限らず、プログラミング全般に言える話です。

次に、上記のメンバをインスペクタから設定できるように改良してみます。

上記クラスでアタッチされたコンポーネントは、インスタンス事に個別の値を設定できるため、以下のように一つのクラスにまとめられるでしょう。

ここで、一つ問題になることがあります。
インスペクタに設定する値は(基本的に)マジックナンバーであるので、上記の例のMEDIUMの値が200から250に変わった場合、それに該当する値を設定している箇所をすべてインスペクタ上から修正する必要があります。
この修正作業はバグの温床になります。

ここで、インスペクタ上からでも定数シンボルに相当するものを設定できないか考えてみました。
最適解ではないと思いますが、ご紹介させていただきます。

実装方法

定数シンボルの定義は、独自の属性定義の機能を用いて実装します。
クラス名は「属性名 + Attribute」とし、PropertyAttributeクラスを継承する必要があります。
今回はConstant属性を独自定義してみます。

定数シンボル名はenumを用いて定義しています。

定数値はDictionaryを用いて定義しています。

上記の書き方を一本化できるスマートな方法が思いつかなかったため、2つに分けて定義しました。
より良い方法があればそちらに切り替えたいと考えているところです。

次に、定数シンボルをインスペクタから設定できるようにするエディタ拡張クラスを定義します。

クラスには属性定義[CustomPropertyDrawer(typeof(ConstantAttribute))]を指定します。
Constant属性のエディタ拡張であることを明示するためののものです。

肝となるのは次の部分です。

定数シンボル名に相当するEnum値をGUIに表示するようにし、インスペクタから設定されたEnum値から実際のInt型の値を取得し、プロパティに設定しています。

使用する側は以下のようになります。

これで、以下のようにインスペクタ上に定数シンボル名を表示できるようになりました。

const-from-inspector

これで、どのような意味を持った値がプロパティに設定されたのか、わかるようになりました。

しかしながら、この方法にも問題点があります。
ConstantAttributeクラスで定義した定数値を変更しても、[Constant]属性が指定されたプロパティに値が即時反映されないということです。
更に、同じ値を持つ定数値が存在するケースに対応できていません。
これらの問題を解消するためには、実行時にEnum型のプロパティを定義し、Enum値をキーにDictionaryから定数値を取得する方法が無難でしょう。

今回の方法はバッドノウハウということで紹介させていただきました。

今月の活動予定

ここ最近猛暑続きですね・・・
皆さまも熱中症にはお気を付けください。

8月になったということで、恒例の月初めの投稿です。
先月は予定していた「Departure from the Void」のWeb版リリースができませんでした。
今月には何とか最低限の形でリリースしたいと考えています。

リリースに時間を要している主な要因はBGMの作り直しです。
Windows版ではMIDI音源によってBGMを再生していましたが、Web版ではMIDI音源は使えず、またBGMもしっかりとした音源にしたいためオーディオデータでの再生で対応しています。
今はそのミキシング作業を行っている段階です。

なんとか落としどころをつけたいところです。

そして、第3週目からは1週間まるまる創作にあてる時間を確保できました。
本業の「Departure from the Void」の整備をやってもよいですが、折角の時間ということで、何か新しいものを一つ作れたらと考えています。
現在はミニゲームを1~2本程度考えています。
1~2日程度で作れる規模のものを想定しています。

ここで挙げた以外にも、色々なものをアウトプットできる1か月にしたいと思います。
そして、Unity関連の備忘録のネタも溜まってきているため、投稿していきたいと思います。

そんなこんなで、今月もよろしくお願いいたします。