控制Unity中脚本的运行顺序
思路就是先拿到脚本和脚本挂的特性值 然后使用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
}
浙公网安备 33010602011771号