29 May 2015

ExecuteInEditMode will run your script in edit mode

Piotr Korzuszek
By Piotr Korzuszek Unity Development Expert

You might be familiar with the workflow that all of your game scripts are working only when you hit the Play button. Did you know that you can force some scripts to be running even when you’re in the edit mode?

Why would you do that? I mean that you may have player scripts, enemies scripts, weapons scripts, environment script, so it makes a little sense for them to execute when the game itself its not running. There are some cases when it can be convenient. Here are some examples:

  • Position constraining – your script may help you position your game objects by constraint object positions using a custom algorithm.
  • Connecting objects – if the ComponentA of the ObjectA requires instance of the ComponentB that is somewhere on the scene, and you are able to find it using your code, then you can do it automatically instead of making the designer do it manually later.
  • In-Editor warnings and errors – Unity will generate a standard set of errors if something is wrong with your code or the initial Unity components setup. Still, you won’t receive any warning if you create a room without doors or windows by mistake. This can be done by a custom script, so the designer is warned when editing.
  • Management scripts – These are scripts that are keeping things in order. Let’s say that your scene has 5 cameras, but all these cameras should have the same FOV parameters. Instead of changing those manually (yes, you can select all of them, but there’s no guarantee that someone else will do the same) you can make your management script adjust all values using one master value. As a result all single camera parameters will be locked and can be changed only by using the management script.

Example

And a lot more… I am sure that you will find a lot more cases when you would use ExecuteInEditMode annotation, but for now let’s see a code example showing how to use it.

using UnityEngine;

// This scripts follows the target object on the straight line
// It is executed in edit mode

[ExecuteInEditMode]
public class Follow : MonoBehaviour {

    // the object to follow
    public Transform follow;

    // max allowed distance
    public float maxDistance = 2;

    void Update() {
        // change this object position only if the distance is greater than maxDistance
        float actualDistance = Vector3.Distance(transform.position, follow.position);
        if (actualDistance > maxDistance) {

            // compute the normalized diff vector
            var followToCurrent = (transform.position - follow.position).normalized;

            // scale it to maxDistance
            followToCurrent.Scale(new Vector3(maxDistance, maxDistance, maxDistance));

            // set the new position
            transform.position = follow.position + followToCurrent;
        }
    }

}

What this code actually does? It makes the current object follow another. It’s no different than usual game script, but pleace notice the [ExecuteInEditMode] annotation before class definition.

Now let’s set up the scene by creating something like a snake. There will be a Head and 3 Body objects. Each body object will follow the body/head on the front, so Body 3 (1) follows Body 2 (2) etc.

execute in edit mode scene setup

 

And here’s how our scene looks like in the Scene view. I’ve added labels to each object to help you tell one from another.

execute in edit mode snakeNow it’s time for the real thing! Please note that everything is done on the Scene view without going into the Play mode!

Be warned!

You may now be thinking of many great scenarios when you would use ExecuteInEditMode annotation, but be careful! If you research a little, you will find out that it is often considered evil and unpredictable. The main reason is that it can easily mess up your scene if not used with caution. If you use it to modify project assets, the modifications may be permanent! This is not the case when you’re in the play mode (except for some rare cases). Also Unity might have trouble with detecting if your scene is actually dirty or not if you constantly change objects’ components in your scripts.

Having this in mind, please consider using any SCM system like Git, SubversionPlastic SCM or Perforce. If you’re not into revision control systems, then at least often back up your project.

Even more tips!

ExecuteInEditMode annotations plays nicely with Application.isPlaying property. Application.isPlaying returns true only when you’re in the play mode or you’re running your game on the target platform, so you can write code like this:

[ExecuteInEditMode]
class Something {
    void Update() {
        if (Application.isPlaying) {
            // code executed in play mode
        } else {
            // code executed in edit mode
        }
    }
}

If you want, you can even use the UnityEditor classes in your game code, but in that case you should use preprocessor directives to cut this code out when building for the target platform. If you don’t do that, you will get compilation errors.

#if UNITY_EDITOR
using UnityEditor;
#endif

[ExecuteInEditMode]
class Something {
    void Update() {
#if UNITY_EDITOR
        Debug.Log("Current scene name: " + EditorApplication.currentScene);
#endif
    }
}

Files

If you’d like to check it by yourself, you can download the unitypackage file, then double-click on it to import its content into your Unity project. You will find there an example scene and a script from above.

Piotr Korzuszek
By Piotr Korzuszek Unity Development Expert
SIRBart

Call The Knights!

    Table of contents