Unity技术分享之动态设置脚本执行顺序
https://blog.csdn.net/s15100007883/article/details/101207442
Unity中调整脚本执行很多人知道的方法是通过ScriptableExecutionOrder设置的, 但是这样设置有个弊端就是 , 这个设置项是依托于ProjectSetting的 , 并不依赖与脚本本身 , 那么有没有可以动态控制脚本的执行顺序的呢 , 答案是肯定有的 ! 下面来介绍三种方法.
文章目录
1. Scriptable Execution Order方式
2. DefaultExecutionOrder属性
3. 自定义属性实现
1. Scriptable Execution Order方式
这种方式不多介绍 , 这是最简单的一种方式了, 简单看一下就行:
优点:
设置简单 ;
执行效率高;
缺点:
依托于工程配置本身 , 如果脚本迁移, 那么执行顺序信息就会丢失.
2. DefaultExecutionOrder属性
这是官方源码部分:
[UsedByNativeCode][AttributeUsage(AttributeTargets.Class)]
public class DefaultExecutionOrder : Attribute
{
public DefaultExecutionOrder(int order)
{
this.order = order;
}
public int order { get; private set; }
}
1
2
3
4
5
6
7
8
9
这个属性在Unity的官方文档里没有记录, 但是确实是官方的东西 ,参数对应[Scriptable Execution Order]方式中的数字.
优点:
1.脚本调用顺序调整方式灵活;
缺点:
1.调整方式过于灵活, 在各自脚本里 , 对工程整体脚本执行顺序不透明, 管理不当会影响其他脚本执行逻辑, 所以建议 , 设置执行顺序的地方要单独提取出来 .
3. 自定义属性实现
参考GIT链接
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}";
[InitializeOnLoadMethod]
private static void Execute() {
var type = typeof( ExecutionOrderAttribute );
var assembly = type.Assembly;
var 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 = "";
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;
}
var script = AssetDatabase.LoadAssetAtPath<MonoScript>( AssetDatabase.GUIDToAssetPath( asset ) );
scripts.Add( script, attribute );
}
var changed = false;
foreach ( var item in scripts ) {
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;
}
}
EditorUtility.ClearProgressBar();
}
#endif
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
使用方式:
using UnityEngine;
using System.Collections;
[ExecutionOrder( 100 )]
public class NormalBehaviour : MonoBehaviour {
void Start() { }
void Update() { }
}
1
2
3
4
5
6
7
8
优点:
设置简单 ;
执行效率高;
缺点:
依托于工程配置本身 , 如果脚本迁移, 那么执行顺序信息就会丢失.
————————————————
版权声明:本文为CSDN博主「月儿圆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/s15100007883/article/details/101207442
浙公网安备 33010602011771号