あらまし
Unity で Collider を設定している際に選択しているオブジェクトの Collider しか表示されない
今回はすべて Mesh が見えているが Mesh が無くても Collider をセットすることもあり
個人的には下図のように見えてほしい
そのため、選択していないオブジェクトの Collider を表示する拡張を作成した
実装
DrawGizmoAttribute
を用いて特定のコライダーの場合 Gizmo を利用して SceneView に描画する
非選択かつ表示されているオブジェクトのコライダーを表示するので
DrawGizmoAttribute
の引数は GizmoType.NonSelected
になる
理想としては private static void DrawCollider(Collider collider, GizmoType type)
を定義して
Collider のタイプを判定して処理をしたかったが 継承したクラスの場合呼び出されなかったので
各 Colliderごとにメソッドを作成している
Gizmo
Gizmo で利用できるのは以下である
- DrawCube 中心とサイズを持つキューブを描画します
- DrawFrustum 位置と回転のために設定されている Gizmos.matrix を使用してカメラの錐台を描画します
- DrawGUITexture シーンにテクスチャを描画します
- DrawIcon シーンビューにアイコンを描画します
- DrawLine from から to に向かってラインを描画します
- DrawMesh メッシュを描画します
- DrawRay from から from + direction に向けてレイを描画します
- DrawSphere center と radius から球体を描画します
- DrawWireCube center と size からキューブを描画します
- DrawWireMesh ワイヤフレームメッシュを描画します
- DrawWireSphere center と radius からワイヤーフレームの球体を描画します
これらには CapsuleCollider
を描画する処理が無いので Handles を利用しておこなう
また CompositeCollider2D
は Mesh の取得方法が分からなかったでの、今回はスキップする
実装結果
下図のように選択していない Collider でも表示することができた
コード
using UnityEditor; using UnityEngine; public static class EditorColliderDrawer { private static readonly Color Color = new Color(0, 0.5f, 0.5f, 1f); [DrawGizmo(GizmoType.NotInSelectionHierarchy)] private static void DrawBoxCollider2D(BoxCollider2D collider, GizmoType type) { Gizmos.color = Color; Gizmos.DrawLine(collider.bounds.min, new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.min.z)); Gizmos.DrawLine(collider.bounds.min, new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.min.z)); Gizmos.DrawLine(collider.bounds.max, new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.max.z)); Gizmos.DrawLine(collider.bounds.max, new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.min.z)); } [DrawGizmo(GizmoType.NonSelected)] private static void DrawCircleCollider2D(CircleCollider2D collider, GizmoType type) { Handles.color = Color; Handles.DrawWireArc(collider.bounds.center, Vector3.forward, Vector3.up * collider.radius, 360f, collider.radius); } [DrawGizmo(GizmoType.NonSelected)] private static void DrawCapsuleCollider2D(CapsuleCollider2D collider, GizmoType type) { Handles.color = Color; var sideHeight = (collider.size.y - collider.size.x) / 2f; var circleHeight = (collider.size.x - collider.size.y) / 2f; if (sideHeight < 0f) sideHeight = 0f; if (circleHeight > 0f) circleHeight = 0f; var top = collider.bounds.center; top.y -= circleHeight; Handles.DrawWireArc(top, Vector3.forward, Vector3.right * collider.size.x / 2f, 180f, collider.size.x / 2f); var bottom = collider.bounds.center; bottom.y += circleHeight; Handles.DrawWireArc(bottom, Vector3.forward, Vector3.left * collider.size.x / 2f, 180f, collider.size.x / 2f); var leftTop = collider.bounds.center; var leftBottom = collider.bounds.center; leftTop.x += collider.size.x / 2f; leftTop.y += sideHeight; leftBottom.x += collider.size.x / 2f; leftBottom.y -= sideHeight; Handles.DrawLine(leftTop, leftBottom); var rightTop = collider.bounds.center; var rightBottom = collider.bounds.center; rightTop.x -= collider.size.x / 2f; rightTop.y += sideHeight; rightBottom.x -= collider.size.x / 2f; rightBottom.y -= sideHeight; Handles.DrawLine(rightTop, rightBottom); } [DrawGizmo(GizmoType.NonSelected)] private static void DrawPolygonCollider2D(PolygonCollider2D collider, GizmoType type) { Gizmos.color = Color; for (var i = 0; i < collider.pathCount; i++) { var paths = collider.GetPath(i); for (var j = 0; j < paths.Length; j++) { var next = j + 1 % paths.Length; if (next >= paths.Length) next = 0; Gizmos.DrawLine(paths[j], paths[next]); } } } [DrawGizmo(GizmoType.NonSelected)] private static void DrawMeshCollider(MeshCollider collider, GizmoType type) { if (collider.sharedMesh == null) return; Gizmos.color = Color; Gizmos.DrawWireMesh(collider.sharedMesh, collider.transform.position, collider.transform.rotation); } [DrawGizmo(GizmoType.NonSelected)] private static void DrawSphereCollider(SphereCollider collider, GizmoType type) { Gizmos.color = Color; Gizmos.DrawWireSphere(collider.center + collider.transform.position, collider.radius); } [DrawGizmo(GizmoType.NonSelected)] private static void DrawBoxCollider(BoxCollider collider, GizmoType type) { Gizmos.color = Color; Gizmos.DrawLine(collider.bounds.min, new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.min.z)); Gizmos.DrawLine(collider.bounds.min, new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.min.z)); Gizmos.DrawLine(collider.bounds.min, new Vector3(collider.bounds.min.x, collider.bounds.min.y, collider.bounds.max.z)); Gizmos.DrawLine(collider.bounds.max, new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.max.z)); Gizmos.DrawLine(collider.bounds.max, new Vector3(collider.bounds.max.x, collider.bounds.max.y, collider.bounds.min.z)); Gizmos.DrawLine(collider.bounds.max, new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.max.z)); Gizmos.DrawLine( new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.min.z), new Vector3(collider.bounds.max.x, collider.bounds.max.y, collider.bounds.min.z) ); Gizmos.DrawLine( new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.min.z), new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.max.z) ); Gizmos.DrawLine( new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.min.z), new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.max.z) ); Gizmos.DrawLine( new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.min.z), new Vector3(collider.bounds.max.x, collider.bounds.max.y, collider.bounds.min.z) ); Gizmos.DrawLine( new Vector3(collider.bounds.min.x, collider.bounds.min.y, collider.bounds.max.z), new Vector3(collider.bounds.max.x, collider.bounds.min.y, collider.bounds.max.z) ); Gizmos.DrawLine( new Vector3(collider.bounds.min.x, collider.bounds.min.y, collider.bounds.max.z), new Vector3(collider.bounds.min.x, collider.bounds.max.y, collider.bounds.max.z) ); } [DrawGizmo(GizmoType.NonSelected)] private static void DrawCapsuleCollider(CapsuleCollider collider, GizmoType type) { var top = collider.center; var bottom = collider.center; top.y += collider.height / 2f - collider.radius; bottom.y -= collider.height / 2f - collider.radius; top += collider.transform.position; bottom += collider.transform.position; Handles.color = Color; var forward = bottom - top; var rot = Quaternion.LookRotation(forward); var pointOffset = collider.radius / 2f; var length = forward.magnitude; var center2 = new Vector3(0f, 0, length); var angleMatrix = Matrix4x4.TRS(top, rot, Handles.matrix.lossyScale); using (new Handles.DrawingScope(angleMatrix)) { Handles.DrawWireDisc(Vector3.zero, Vector3.forward, collider.radius); Handles.DrawWireArc(Vector3.zero, Vector3.up, Vector3.left * pointOffset, -180f, collider.radius); Handles.DrawWireArc(Vector3.zero, Vector3.left, Vector3.down * pointOffset, -180f, collider.radius); Handles.DrawWireDisc(center2, Vector3.forward, collider.radius); Handles.DrawWireArc(center2, Vector3.up, Vector3.right * pointOffset, -180f, collider.radius); Handles.DrawWireArc(center2, Vector3.left, Vector3.up * pointOffset, -180f, collider.radius); DrawLine(collider.radius, 0f, length); DrawLine(-collider.radius, 0f, length); DrawLine(0f, collider.radius, length); DrawLine(0f, -collider.radius, length); } } private static void DrawLine(float arg1, float arg2, float forward) { Handles.DrawLine(new Vector3(arg1, arg2, 0f), new Vector3(arg1, arg2, forward)); } }