経緯
何かしらのサンプル作成や実体のないGameObjectの場所把握などにUnityのギズモ描画は利用することが多い。
デフォルトでは下記画像の通りのギズモ描画がサポートされている。
このほかシリンダーやカプセルも使いたい場合の簡単なサンプルを作成した
出来上がるもの
何はともあれ出来上がるものを見てみよう
サポートしているのは以下の通り( gif画像が荒いのは許して... )
スクリプト
今回のスクリプトはあくまでサンプルなのでエディタ拡張のコードも一つのファイルに収めています。
気になる人はエディタ用のコードとそうでないものとを分けると精神衛生上よろしいです。
using UnityEngine;
# if UNITY_EDITOR
using UnityEditor;
# endif
namespace sample
{
public class Sample : MonoBehaviour
{
// 描画モード.
public enum DrawMode
{
Solid,
Wire,
}
[SerializeField] Color gizmoColor;
[SerializeField] DrawMode gizmoDrawMode;
[SerializeField] PrimitiveType usePrimitiveType = PrimitiveType.Cube;
[SerializeField] Mesh mesh = null;
void OnDrawGizmos()
{
if (mesh == null) return;
Gizmos.color = gizmoColor;
switch (gizmoDrawMode)
{
case DrawMode.Solid:
Gizmos.DrawMesh(mesh, transform.position, transform.rotation, transform.localScale);
break;
case DrawMode.Wire:
Gizmos.DrawWireMesh(mesh, transform.position, transform.rotation, transform.localScale);
break;
}
}
# if UNITY_EDITOR
// エディタ拡張部分.
[CustomEditor(typeof(Sample))]
public class SampleEditor : Editor
{
public override void OnInspectorGUI()
{
var component = target as Sample;
GUI.changed = false;
component.gizmoColor = EditorGUILayout.ColorField("Gizmo Color", component.gizmoColor);
component.gizmoDrawMode = (DrawMode)EditorGUILayout.EnumPopup("Draw Mode", component.gizmoDrawMode);
if (GUI.changed) EditorUtility.SetDirty(component);
// プリミティブタイプが変更された場合,メッシュを差し替える.
GUI.changed = false;
component.usePrimitiveType = (PrimitiveType)EditorGUILayout.EnumPopup(component.usePrimitiveType);
if (GUI.changed)
{
EditorUtility.SetDirty(component);
GameObject tempPrimitive = GameObject.CreatePrimitive(component.usePrimitiveType);
component.mesh = tempPrimitive.GetComponent<MeshFilter>().sharedMesh;
GameObject.DestroyImmediate(tempPrimitive);
}
// 取得したメッシュを確認できるようにしているだけ.
EditorGUILayout.ObjectField(component.mesh, typeof(Mesh));
}
}
# endif
}
}
肝となるのはエディタ拡張部分の↓この部分
// プリミティブタイプが変更された場合,メッシュを差し替える.
GUI.changed = false;
component.usePrimitiveType = (PrimitiveType)EditorGUILayout.EnumPopup(component.usePrimitiveType);
if (GUI.changed)
{
EditorUtility.SetDirty(component);
GameObject tempPrimitive = GameObject.CreatePrimitive(component.usePrimitiveType);
component.mesh = tempPrimitive.GetComponent<MeshFilter>().sharedMesh;
GameObject.DestroyImmediate(tempPrimitive);
}
GUI側のInspectorに変更があるか否かのチェックをとり変更がある場合、
- プリミティブオブジェクトの生成(参考ページ)
- 生成したオブジェクトからsharedMeshの取り出し
- 生成したプリミティブオブジェクトの削除
の手順で差し替えています。