「ギズモ」と言われると、ドラゴンクエストの雲のモンスターが思い浮かびます。
ギズモとは (ギズモとは) [単語記事] - ニコニコ大百科
当然のことですが、今日の議題に一切関係ないことです。
ただ、どうしても雲をいじっている気分になるんですよ。
こんな気分で勉強できるのでしょうか。
この記事にはUnity2017.2.0f3を使用しています。
バカにだけ見えないというわけではない
まずはこのシーンビューの画像を見てほしい。
このシーンには自作位置情報コンポーネントであるPoint
が配置されているのだが、わかるだろうか。
もちろん、シーンビューには見えない。
Inspector上のGameObjectを選択すれば、ハンドルが出るので位置は特定できる。
ちなみにPoint
クラスはこのようなスクリプトになっている。
Point.cs
using UnityEngine; public class Point : MonoBehaviour { public enum EType { Item, Magic, Trap, } [SerializeField] private EType m_type = default( EType ); [SerializeField, Range( 0.0f, 10.0f )] private float m_radius = 0.0f; public EType Type { get { return m_type; } } public float Radius { get { return m_radius; } } } // class Point
このPoint
クラスには「半径」「タイプ」という二つの情報を持っている。
シーンビュー上からはさっぱりわからない。
スクリプトの上では各クラスはプロパティを経由して「半径」と「タイプ」の情報を取得することが出来るので、ゲーム内にいるオブジェクト達は問題なく動作出来ることだろう。
だが、私がシーンビューを見る限りその情報を一切取得することが出来ない。
このプロジェクトの創造主たる私だけがわからないのだ!
何というイジメであろうか。
このような仲間外れがある限り、この国は決してよくなっていかないだろう。
シーンビュー上で情報が取得できるようにして、良い国を目指していこうと思う。
OnDraw関数でサクッと解決
さて、というわけでエディタ拡張する必要があるので、Unityエディタ拡張バイブルを開きます。
Unityが目まぐるしく更新されていく中、随分前に購入したこの本は常に現役なのが素晴らしい。
バイブルを読む限り、今回はギズモというものの描画処理を追加してあげれば解決できそうだね。
えーと何々、OnDrawGizmosSelected()
を追記すればいいのか。
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnDrawGizmosSelected.htmldocs.unity3d.com
Point.cs
void OnDrawGizmosSelected() { Gizmos.color = Color.green; Gizmos.DrawSphere( transform.position, 0.1f ); Gizmos.DrawWireSphere( transform.position, Radius ); }
おっ、いいですね。
範囲がすごくわかりやすく表示されておりまする。
ただこのOnDrawGizmosSelected()
で選択されていないと表示されないみたいですね。
それはそれでいいんですが、今回シーン中に複数のオブジェクトが配置されています。
選択されていないオブジェクトも常時ギズモが表示されるようになってもらいたいものです。
えーとそんなときは……、これだ、OnDrawGizmos()
だ。
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnDrawGizmos.htmldocs.unity3d.com
Point.cs
void OnDrawGizmos() { Gizmos.color = Color.green; Gizmos.DrawSphere( transform.position, 0.1f ); Gizmos.DrawWireSphere( transform.position, Radius ); }
あらあら、いいんじゃないですか。
これでシーンビューから視覚的に情報が分かるようになって、作業が格段に向上できそうです。
えがったえがった。
ランタイムの処理とエディタの処理は、どうせ喧嘩するだろうから分けようか
さて、このままでも一向にかまわないのですが、ランタイムの処理であるPoint.cs部分にエディタ用の処理をがっつり記述するのはちょっと……、という気分になるときがあるかもしれません。
というわけで、ランタイムの処理とエディタの処理を分けてしまいましょう。
先ほどのOnDrawGizmosSelected()
とOnDrawGizmos()
は破棄します。
DrawGizmoAttribute
を使えば、別クラスにギズモの描画クラスが記述できるみたいです。
https://docs.unity3d.com/ScriptReference/DrawGizmo.htmldocs.unity3d.com
さきほどのOnDrawGizmos()
とOnDrawGizmosSelected()
のように、「選択されていない時に表示したい」「選択されたら表示したい」などはDrawGizmo
のenumを利用して指定するみたいです。
DrawGizmo
はFlagタイプのようなので、ビットOR演算子で複数指定できそうです。
https://docs.unity3d.com/ScriptReference/GizmoType.htmldocs.unity3d.com
それじゃ、Point
クラスのギズモ描画処理用のPointGizmoEditor
クラスを作成しましょう。
PointGizmoEditor.cs
using UnityEngine; using UnityEditor; public class PointGizmoEditor { [DrawGizmo( GizmoType.NonSelected | GizmoType.Selected )] private static void DrawPointGizmos( Point i_point, GizmoType i_gizmoType ) { Color color = Color.white; // 選択されていないときの場合は、色をタイプごと変えてみたよ。 if( ( i_gizmoType & GizmoType.NonSelected ) != 0 ) { switch( i_point.Type ) { case Point.EType.Item: color = Color.green; break; case Point.EType.Magic: color = Color.cyan; break; case Point.EType.Trap: color = Color.yellow; break; default: break; } } Gizmos.color = color; Vector3 pos = i_point.transform.position; Gizmos.DrawSphere( pos, 0.1f ); Gizmos.DrawWireSphere( pos, i_point.Radius ); } } // class PointGizmoEditor
あら素晴らしい。
先ほどの処理に、Point
クラスのタイプによって色を変える処理も加えてみました。
これでシーンビューを見るだけで情報が丸わかりになりましたねー。
ゲームビューでも見ようと思えばギズモは見える
さて、これで今回の作業はこれでおしまいなわけですが、こんな疑問があります。
このシーンビューで表示したギズモを、ゲームビューでも見えないものでしょうか。
んー、出来るのかなぁ、そんなこと。
ギズモって開発用のものだからなぁ。
ゲームビューの右上の「Gizmos」ボタンを押すことでゲームビューにも表示できるようですね。
ただ、ギズモ用の描画処理がかかるため、確実に処理は重くなるので注意が必要です。