Skip to content

Instantly share code, notes, and snippets.

@noisecrime
Created November 10, 2016 19:47
Show Gist options
  • Save noisecrime/badd36a25f238a40f8678b364a33cf9c to your computer and use it in GitHub Desktop.
Save noisecrime/badd36a25f238a40f8678b364a33cf9c to your computer and use it in GitHub Desktop.
Editor class that will automatically set the scriptExecutionOrder based on using a ScriptExecutionAttribute.
// ScriptExecutionAssignment
// NoiseCrime
// 11.10.2016
// 05.06.2016
//
//
// Editor class that will automatically set the scriptExecutionOrder based on using a ScriptExecutionAttribute.
// See ScriptExecutionAttribute.cs Gist!
// The class is called automatically everytime Unity recompiles the project - see [InitializeOnLoad]
//
// This script MUST be placed into an Editor Folder in your Unity Project.
// Requires Script names to match class name.
// Likely only works with a single class defined per file.
// Unfortunately the script will also execute everytime you run the project in the editor ( play ), so use defines below to control behaviour.
//
// ENABLE_SCRIPT: If NOT defined the script will not run.
// ENABLE_ASSIGNMENT: If NOT defined this will prevent execution of the script.
// ENABLE_LOGGING: If defined will log ( sorted by order ) to the console all found classes using the ScriptExecutionAttribute and their script order.
// ENABLE_MONO_LOGGING: If defined will log all scripts in mono that are not using default ScriptExecution value.
// #define ENABLE_SCRIPT
#define ENABLE_LOGGING
#define ENABLE_MONO_LOGGING
#define ENABLE_ASSIGNMENT
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Collections.Generic;
[InitializeOnLoad]
public class ScriptExecutionAssignment : Editor
{
static ScriptExecutionAssignment()
{
#if ENABLE_SCRIPT
if( EditorApplication.isCompiling || EditorApplication.isPaused || EditorApplication.isPlaying) return;
#if ENABLE_MONO_LOGGING
LogAllMonoScripts();
#endif
AssignExecutionOrderToMonoScripts();
#else
Debug.LogWarning("EDITOR: ScriptExecutionAssignment is disabled - check script define.");
#endif
}
static void LogAllMonoScripts()
{
Dictionary<string, int[]> executionOrderLogging = new Dictionary<string, int[]>();
// Lock Assemblies
EditorApplication.LockReloadAssemblies();
foreach (MonoScript monoScript in MonoImporter.GetAllRuntimeMonoScripts())
{
Type monoClass = monoScript.GetClass();
if( monoClass != null)
{
int executionOrderOriginal = MonoImporter.GetExecutionOrder(monoScript);
if(executionOrderOriginal != 0) executionOrderLogging.Add( monoScript.name, new int[ 2 ] { executionOrderOriginal, executionOrderOriginal } );
}
}
// Unlock Assemblies
EditorApplication.UnlockReloadAssemblies();
LogResults("GetExecutionOrder", executionOrderLogging);
}
static void AssignExecutionOrderToMonoScripts()
{
#if ENABLE_LOGGING
Dictionary<string, int[]> executionOrderLogging = new Dictionary<string, int[]>();
#endif
// Lock Assemblies
EditorApplication.LockReloadAssemblies();
foreach (MonoScript monoScript in MonoImporter.GetAllRuntimeMonoScripts())
{
Type monoClass = monoScript.GetClass();
if( monoClass != null)
{
Attribute att = Attribute.GetCustomAttribute(monoClass, typeof(ScriptExecutionAttribute));
if( att != null)
{
int executionOrderTarget = ((ScriptExecutionAttribute)att).executionIndex;
int executionOrderOriginal = MonoImporter.GetExecutionOrder(monoScript);
#if ENABLE_LOGGING
executionOrderLogging.Add( monoScript.name, new int[ 2 ] { executionOrderOriginal, executionOrderTarget } );
#endif
#if ENABLE_ASSIGNMENT
// It is important not to set the execution order if the value is already correct!
if (executionOrderOriginal != executionOrderTarget)
{
MonoImporter.SetExecutionOrder(monoScript, executionOrderTarget);
#if ENABLE_LOGGING
Debug.LogWarning(Decorate.Warning("The script " + monoScript.name + " was not set to correct Script Execution Order - it has been fixed and set to " + executionOrderTarget + " from " + executionOrderOriginal));
#endif
}
#endif
}
}
}
// Unlock Assemblies
EditorApplication.UnlockReloadAssemblies();
#if ENABLE_LOGGING
LogResults("ScriptExecutionAttribute", executionOrderLogging);
#endif
}
// Simple logging to console with the dictionary of found classes sorted by execution order.
static void LogResults( string title, Dictionary<string, int[]> results )
{
if ( results.Count > 0 )
{
string logging = title + ": Found Types\n";
foreach ( KeyValuePair<string, int[]> item in results.OrderBy( key => key.Value[ 1 ] ) )
logging += string.Format( "<color={0}>ScriptExecutionAttribute: Current: {0} Target: {1} Type: {2}</color>\n", item.Value[ 0 ], item.Value[ 1 ], item.Key, ( item.Value[ 0 ] == item.Value[ 1 ] ? "#F0F0F0" : "#FF0000" ) );
Debug.Log( logging );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment