#if UNITY_EDITOR square brackets

Hello, I’ve got a script that contains the following:

#if UNITY_EDITOR
    [DrawGizmo(GizmoType.Selected)]
    static void DrawGizmo(SlotInspector target, GizmoType gizmoType) {
        if (target.MapBehaviour == null) {
            return;
        }
        Gizmos.color = Color.blue;
        Gizmos.DrawWireCube(target.MapBehaviour.GetWorldspacePosition(target.MapBehaviour.GetMapPosition(target.transform.position)), Vector3.one * InfiniteMap.BLOCK_SIZE);
    }
#endif

As I currently understand, “#if UNITY_EDITOR” is a pre-processor tag and the code before “#endif” will only run when playing the game in the editor. At least in my case, this gizmo is only visible in the editor’s “scene” view.

However, I don’t understand why the next line “[DrawGizmo(GizmoType.Selected)]” is in square brackets.

My second question is that the signature used in that line doesn’t seem to match the signature in the definition below - it passes in a GizmoType parameter, but not a SlotInspector parameter (and the definition below looks like it wants both).

It’s also worth mentioning that I’ve seen this page: Unity - Scripting API: DrawGizmo

I don’t really understand what the relationship is between the “DrawGizmo()” function on that page, and the one that gets defined in the snippet above. Does one overwrite the other?

These are called attributes or decorators.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/

1 Like

A few things are being conflated here. You’re correct about what #if does, with the slight adjustment that that isn’t what runs when the condition is true, it’s what compiles. The advantage of #if over a regular if statement is that the code inside doesn’t need to even be legal code when the condition isn’t met.

The thing in the brackets is unrelated to the #if statement. It’s called an Attribute - it’s something the compiler can apply to the property/method/member that follows. A more easily understood example is the Range attribute:

[Range(0f, 100f)]
public float percentage = 100f;

Put this into a script and check it out in the inspector - Unity’s inspector finds the Range attribute and if present, it alters the way that field appears in the inspector.

In this case, that attribute seems to indicate “this is a function to call anytime we’re about to draw gizmos of X type”. The function is then called, but the parameters of the function aren’t necessarily related to the parameters you see in the attribute. It might help to know that that method doesn’t need to be called DrawGizmos, and that’s probably only adding to the confusion.

1 Like

Thanks for this info, I’ve seen and used this before:

[Range(0f, 100f)]
public float percentage = 100f;

The documentation page says that “The DrawGizmo attribute allows you to supply a gizmo renderer for any Component”. So going by that and what you’ve said, I take it that it’s effectively a signpost saying “the next function is what you use to draw a gizmo (and you should draw it when this script’s parent is selected)”. Then we get the aforementioned function. Is that along the right lines?

Presumably, that “DrawGizmo” attribute tells the compiler to use something like a delegate to call the following function whenever the parent of this script is selected.

[Just as a note, and maybe a more general question, I tried to select the “DrawGizmo” attribute text in VSCode and then press F12 to “inspect” the definition, but it didn’t lead anywhere helpful, should I be able to look at how that “DrawGizmo” attribute actually functions somehow?]

Yep, you got it.

Generally the stuff that leads into the bowels of the engine can’t be read that way, but it’s usually documented if you google for like “unity SomeFunctionName”.

One note about googling for docs on attributes though, and this is something that is AFAIK unique within C#, the name of an Attribute is sometimes but not always ended with the word Attribute, but C# recognizes it with or without the Attribute part.
So you can use this:

RangeAttribute(0f,100)
public float percentage = 100f;

And it works the same as if it was just Range().

DrawGizmo is one of the few attributes whose name doesn’t end in Attribute.

1 Like

Attributes do not do anything on their own. They are just metadata that are stuck to methods, classes, members or parameters. The DrawGizmo attribute is defined here. In many cases that metadata may be used from native code of Unity. However in the case of the DrawGizmo attribute, the extraction of the methods is done here through reflection. This method is most likely called from the native engine core when the scripts are recompiled.