思路就是先拿到脚本和脚本挂的特性值 然后使用monoImportor.Set修改执行顺序
using System; using System.Collections.Generic; #if UNITY_EDITOR using System.IO; using UnityEditor; #endif using UnityEngine; [AttributeUsage( AttributeTargets.Class, Inherited = false, AllowMultiple = false )] sealed class ExecutionOrderAttribute : Attribute { public readonly int ExecutionOrder = 0; public ExecutionOrderAttribute( int executionOrder ) { ExecutionOrder = executionOrder; } #if UNITY_EDITOR private const string PB_TITLE = "Updating Execution Order"; private const string PB_MESSAGE = "Hold on to your butt, Cap'n!"; private const string ERR_MESSAGE = "Unable to locate and set execution order for {0}"; //这个特性类似 InitializeLoad 点击运行的时候会加载脚本 或者你在vs修改了什么东西 也会加载一次 [InitializeOnLoadMethod] private static void Execute() { //用类型拿到这个程序集中所有的脚本 Type type = typeof( ExecutionOrderAttribute ); //我糙 真是服了 用var居然不用引用命名空间 var assembly = type.Assembly; //可以尝试进行打印查看程序及中的类集合 Type[] types = assembly.GetTypes(); var scripts = new Dictionary<MonoScript, ExecutionOrderAttribute>(); var progress = 0f; var step = 1f / types.Length; foreach ( var item in types ) { //拿到类身上的特性 var attributes = item.GetCustomAttributes( type, false ); //如果脚本上的特性大于一个跳过继续 if ( attributes.Length != 1 ) continue; var attribute = attributes[0] as ExecutionOrderAttribute; var asset = ""; //从Asset中拿到这个脚本的唯一标识符(就是哪个guid特性里面的值) var guids = AssetDatabase.FindAssets( string.Format( "{0} t:script", item.Name ) ); if ( guids.Length > 1 ) { foreach ( var guid in guids ) { var assetPath = AssetDatabase.GUIDToAssetPath( guid ); var filename = Path.GetFileNameWithoutExtension( assetPath ); if ( filename == item.Name ) { asset = guid; break; } } } else if ( guids.Length == 1 ) { asset = guids[0]; } else { Debug.LogErrorFormat( ERR_MESSAGE, item.Name ); return; } //将guid码转化为资源路径然后加载对应的脚本 MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>( AssetDatabase.GUIDToAssetPath( asset ) ); //将脚本和对应的特性加载到集合中 scripts.Add( script, attribute ); } bool changed = false; foreach ( var item in scripts ) { //查看七楼八楼的对应解释 //https://forum.unity.com/threads/script-execution-order-manipulation.130805/ if ( MonoImporter.GetExecutionOrder( item.Key ) != item.Value.ExecutionOrder ) { changed = true; break; } } if ( changed ) { foreach ( var item in scripts ) { var cancelled = EditorUtility.DisplayCancelableProgressBar( PB_TITLE, PB_MESSAGE, progress ); progress += step; if ( MonoImporter.GetExecutionOrder( item.Key ) != item.Value.ExecutionOrder ) { MonoImporter.SetExecutionOrder( item.Key, item.Value.ExecutionOrder ); } if ( cancelled ) break; } } Debug.Log("排序行为执行"); EditorUtility.ClearProgressBar(); } #endif }