When developing games with Unity, it is very common to implement visual aids (gizmos and handles) on the editor in scripts to increase development efficiency. However, even if the code runs normally in the editor and can be played back, when you run a "real device build" on Android, iOS, PC, etc., you may encounter a problem where the build fails with an error such as The name 'Handles' does not exist in the current context or The namespace 'UnityEditor' could not be found.

In this article, we will investigate the root cause of the compile error of editor-specific code that occurs during build, and explain in detail a solution approach to safely separate editor functions and actual code in practice.

For beginners: How would you describe this problem in real life?

Let's compare this build error problem to the "backstage rehearsal" and "actual stage" of a play.

During the rehearsal stage (on the Unity editor), in order for the director and cast to confirm their standing positions, they put cross-shaped vinyl tape (such as gizmos or handles) on the stage floor, or issue instructions using a megaphone (a tool exclusive to the editor). These are absolutely necessary props to make rehearsals go smoothly.

However, when the actual theater performance (real machine build) begins, if there is tape with a cross on the stage or if the stage manager is wandering around with a megaphone, there will be loud boos from the audience, and the rules of the actual theater (the actual machine's runtime environment) do not allow for such a production. A physical build is the real deal, and all editor-specific instructions and props must be put away. What we should do is to hide these editor-specific tools (codes) neatly during the performance, or store them in the dressing room (Editor folder) in advance.

Problem symptoms and specific phenomena

When this build error occurs, the following symptoms are observed.

  • When I press the play button on the Unity editor, it works perfectly without any errors.
  • As soon as I run a build from File > Build Settings, a bunch of red errors appear in the console window and the build process is forced to abort.
  • Many of the error messages point to using declarations in the UnityEditor namespace or some drawing methods in Handles and Gizmos (e.g. related to Handles.DrawWireDisc and EditorGUI).

Assumed cause: Why does an error occur when building the actual machine?

The Unity engine manages the code base separately, with a mechanism for running the game in the editor and a mechanism for writing the final executable file. All APIs included in the UnityEditor namespace are functions for operating and controlling the Unity editor (development environment) itself, and are completely removed from the engine side when building the actual device.

Therefore, when the build pipeline is executed, if a reference to a class in using UnityEditor; or UnityEditor remains in the process of compiling code for the actual device, the compiler will determine that ``such a class or function does not exist in the library for the actual device'' and generate an error. The editor's helpful aids become a hindrance to compilation during build time.

Specific solutions and approaches

There are two main approaches to solving this problem: Use them appropriately depending on the project design and the role of the script.

Approach A: Conditional compilation with preprocessor macros

If you want to write auxiliary drawing logic for the editor (e.g. OnDrawGizmos) in a script that is attached to a game object and runs on the actual device, use #if UNITY_EDITOR and #endif to enclose the code. This allows the compiler to completely ignore that range of code when building the actual device.

using UnityEngine;
// Preventing UnityEditor from being referenced and causing an error when building the actual device
#if UNITY_EDITOR
using UnityEditor;
#endif

public class RangeIndicator : MonoBehaviour
{
    public float detectionRadius = 5.0f;

    // The logic in the game is also executed on the actual machine.
    void Update()
    {
        // Enemy search processing, etc.
    }

    // Visualization process on the editor
    void OnDrawGizmos()
    {
        // The Gizmos class itself is included in UnityEngine, so it can be called on the actual machine, but
        // The Handles class is included in UnityEditor, so it needs to be enclosed in a macro.
        #if UNITY_EDITOR
        Handles.color = Color.green;
        // Draw a circle directly above the transform
        Handles.DrawWireDisc(transform.position, Vector3.up, detectionRadius);
        #endif
    }
}

Approach B: Physical file separation into Editor folder

If the script you created is a file that is used 100% only in the editor, such as a custom inspector (inherited from the Editor class) or a unique menu window (EditorWindow), control it with the folder structure. Create a folder named 'Editor' (for example, Assets/Scripts/Editor) somewhere under the Assets folder of your project and physically move the script file into it. Unity automatically organizes the code in the folder named "Editor" into an editor-only assembly and completely excludes it from the target of the actual build.

Confirmation checklist useful in practice

This is a preliminary checklist to prevent build errors caused by editor code.

If
Confirmation points Countermeasures/Rules
File location Are all files that inherit from the Editor class located in a folder named Editor?
Check using clauseusing UnityEditor; is in a script outside the Editor folder, is it always enclosed in #if UNITY_EDITOR?
Where to use Handles etc. When calling Handles or EditorGUI in OnDrawGizmos or OnDrawGizmosSelected in a normal script, are they enclosed in macros?

Summary

The API for the Unity editor makes development very convenient, but it needs to be clearly differentiated during the compilation process at build time. Prevent build errors and maintain a smooth deployment pipeline even in team development by correctly understanding and properly using partial exclusion using the #if UNITY_EDITOR macro and physical assembly separation using the Editor folder.