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.
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.
Now 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, Subversion, Plastic 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.