Draw 2d circle with Gizmos

Hi!

I’m creating a script that draws gizmos for all 2D colliders in my 2D scene.
My question is: how do I draw a gizmo for a 2D circle the same way you see gizmos when
selecting an object?
The only function in Gizmos that I find close to this is “DrawWireSphere()” but it draws a sphere and i can only give it a position and radius and not a rotation.

Here’s what I want (from a 3D perspective):
36048-want.png

Here’s what I have right now (from a 3D perspective):
36050-have.png

So I simply just want to draw the circle in the xy-plane and have the options to rotate on any axis.

To see the Z-rotation from a 2D-perspective I will just draw lines like a cross over the circle. I can do that now aswell but it will be confusing to see all the sphere circles at the same time.

EDIT:
The circle i want to draw should be for all game objects in the scene and not only targeted game objects.

SOLUTION

As suggested by buckius82 below, a solution for this is to make a monobehavior script that retrieves all CircleCollider2D’s in the scene and then draw wire discs (UnityEdtior.Handles.DrawWireDisc) under the OnDrawGizmos() method.

Example:

private void OnDrawGizmos(){
  UnityEditor.Handles.color = Color.yellow;
  CircleCollider2D[] colliders = FindObjectsOfType (typeof(CircleCollider2D)) as Collider2D[];
  foreach(CircleCollider2D collider in colliders){
    UnityEditor.Handles.DrawWireDisc(collider.transform.position ,Vector3.back, collider.radius);
  }
}

Note that this may take some performance if there are alot of colliders in the scene.

I wanted to make 2d circle in 3d to represent spread in the editor.

Look At editor.handles

using UnityEditor;
using UnityEngine;
public class customclassEditor: MonoBehaviour
{
    public float variance;    // This much variance 
    public float maxdistance; // at this distance
    
}
        
using UnityEditor;
using UnityEngine;
using System.Collections;

[CustomEditor(typeof(customclass))]
public class customclassEditor: Editor 
{
    
    private customclass c;
        
    public void OnSceneGUI () 
    {
    	c = this.target as customclass;
    	Handles.color = Color.red;
    	Handles.DrawWireDisc(c.transform.position +(c.transform.forward *c.Range) // position
                                      , c.transform.forward                       // normal
                                      , c.variance);                              // radius
    }
 }

i hop this can get you started

I also wanted to draw gizmo disks. Here’s the solution I came up with, which doesn’t require using an editor script. You can stick it into a static utility class, then call it with transform.DrawGizmoDisk(radius: 0.5f) or whatever.

        private const float GIZMO_DISK_THICKNESS = 0.01f;

        public static void DrawGizmoDisk(this Transform t, float radius)
        {
            Matrix4x4 oldMatrix = Gizmos.matrix;
            Gizmos.color = new Color(0.2f, 0.2f, 0.2f, 0.5f); //this is gray, could be anything
            Gizmos.matrix = Matrix4x4.TRS(t.position, t.rotation, new Vector3(1, GIZMO_DISK_THICKNESS, 1));
            Gizmos.DrawSphere(Vector3.zero, radius);
            Gizmos.matrix = oldMatrix;
        }

Bit hacky (it’s just a squished sphere) but good enough for visualizing a radius!
example of two squished gizmos spheres in action

You can also easily modify this to draw a wire sphere instead, or both at the same time (as pictured here), but since this is a squished 3d gizmo, if you draw the wire sphere, there’s no avoiding the “cross” that shows up with it. Still, it’s probably the closest you can get without having to use the custom editor APIs (I consider that a plus if I am otherwise not gonna need a custom editor!)

150297-screenhunter-4628.png

Here’s an example of drawing the squished wire sphere that takes a position as an argument rather than being an extension method of a transform.

public static void DrawWireDisk(Vector3 position, float radius, Color color)
    {
        Color oldColor = Gizmos.color;
        Gizmos.color = color;
        Matrix4x4 oldMatrix = Gizmos.matrix;
        Gizmos.matrix = Matrix4x4.TRS(position, Quaternion.identity, new Vector3(1, GIZMO_DISK_THICKNESS, 1));
        Gizmos.DrawWireSphere(Vector3.zero, radius);
        Gizmos.matrix = oldMatrix;
        Gizmos.color = oldColor;
    }

@davidisak, I think you need to make your custom editor script to do this.(correct me if i am wrong.). You want to use Handles.DrawWireDisc. use Handles for more customization.

Here’s a solution using Gizmos. Only tested this so it displays in a world space canvas in the Z direction but can be adjusted in the Euler method to display on any angle.

float corners = 11; // How many corners the circle should have
float size = 10; // How wide the circle should be
Vector3 origin = transform.position; // Where the circle will be drawn around
Vector3 startRotation = transform.right * size; // Where the first point of the circle starts
Vector3 lastPosition = origin + startRotation;
float angle = 0;
while (angle <= 360)
{
    angle += 360 / corners;
    Vector3 nextPosition = origin + (Quaternion.Euler(0, 0, angle) * startRotation);
    Gizmos.DrawLine(lastPosition, nextPosition);
    Gizmos.DrawSphere(nextPosition, 1);

    lastPosition = nextPosition;
}

I wanted a version of @James2Games solution that takes a normal and position instead of a full transform. Here’s what I came up with:

public static void DrawGizmosCircle(Vector3 pos, Vector3 normal, float radius, int numSegments)
{
    // I think of normal as conceptually in the Y direction.  We find the
    // "forward" and "right" axes relative to normal and I think of them 
    // as the X and Z axes, though they aren't in any particular direction.
    // All that matters is that they're perpendicular to each other and on
    // the plane defined by pos and normal.
    Vector3 temp = (normal.x < normal.z) ? new Vector3(1f, 0f, 0f) : new Vector3(0f, 0f, 1f);
    Vector3 forward = Vector3.Cross(normal, temp).normalized;
    Vector3 right = Vector3.Cross(forward, normal).normalized;

    Vector3 prevPt = pos + (forward * radius);
    float angleStep = (Mathf.PI * 2f) / numSegments;
    for (int i = 0; i < numSegments; i++)
    {
        // Get the angle for the end of this segment.  If it's the last segment,
        // use the angle of the first point so the last segment meets up with
        // the first point exactly (regardless of floating point imprecision).
        float angle = (i == numSegments - 1) ? 0f : (i + 1) * angleStep;

        // Get the segment end point in local space, i.e. pretend as if the
        // normal was (0, 1, 0), forward was (0, 0, 1), right was (1, 0, 0),
        // and pos was (0, 0, 0).
        Vector3 nextPtLocal = new Vector3(Mathf.Sin(angle), 0f, Mathf.Cos(angle)) * radius;

        // Transform from local to world coords.  nextPtLocal's x,z are distances
        // along its axes, so we want those as the distances along our right and
        // forward axes.
        Vector3 nextPt = pos + (right * nextPtLocal.x) + (forward * nextPtLocal.z);

        Gizmos.DrawLine(prevPt, nextPt);

        prevPt = nextPt;
    }
}

In case someone is still looking, I made this quick-and-dirty method for drawing circles in 3D with Gizmos. It doesn’t use disks, so it draws actual circles. This method can be used in any OnDrawGizmos method.

private void DrawGizmoCircle(Vector3 circleCenter, Vector3 circleNormal, float circleRadius, int segments = 32)
    {
        Vector3 radiusVector = Mathf.Abs(Vector3.Dot(circleNormal, Vector3.right)) - 1f <= Mathf.Epsilon 
            ? Vector3.Cross(circleNormal, Vector3.forward).normalized 
            : Vector3.Cross(circleNormal, Vector3.right).normalized;
        radiusVector *= circleRadius;
        float angleBetweenSegments = 360f / segments;
        Vector3 previousCircumferencePoint = circleCenter + radiusVector;
        for (int i = 0; i < segments; ++i)
        {
            radiusVector = Quaternion.AngleAxis(angleBetweenSegments, circleNormal) * radiusVector;
            Vector3 newCircumferencePoint = circleCenter + radiusVector;
            Gizmos.DrawLine(previousCircumferencePoint, newCircumferencePoint);
            previousCircumferencePoint = newCircumferencePoint;
        }
    }

You can see it in the cyan circle in the intersection between spheres.