Unity技术分享之动态设置脚本执行顺序

Unity中调整脚本执行很多人知道的方法是通过ScriptableExecutionOrder设置的, 但是这样设置有个弊端就是 , 这个设置项是依托于ProjectSetting的 , 并不依赖与脚本本身 , 那么有没有可以动态控制脚本的执行顺序的呢 , 答案是肯定有的 ! 下面来介绍三种方法.

1. Scriptable Execution Order方式

Scriptable Execution Order的方式
这种方式不多介绍 , 这是最简单的一种方式了, 简单看一下就行:

优点:

  1. 设置简单 ;
  2. 执行效率高;

缺点:

  1. 依托于工程配置本身 , 如果脚本迁移, 那么执行顺序信息就会丢失.

2. DefaultExecutionOrder属性

这是官方源码部分:

	[UsedByNativeCode][AttributeUsage(AttributeTargets.Class)]
    public class DefaultExecutionOrder : Attribute
    {
        public DefaultExecutionOrder(int order)
        {
            this.order = order;
        }
        public int order { get; private set; }
    }

这个属性在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
}

使用方式:

using UnityEngine;
using System.Collections;

[ExecutionOrder( 100 )]
public class NormalBehaviour : MonoBehaviour {
    void Start() {    }
    void Update() {    }
}

结果显示

优点:

  1. 设置简单 ;
  2. 执行效率高;

缺点:

  1. 依托于工程配置本身 , 如果脚本迁移, 那么执行顺序信息就会丢失.
发布了31 篇原创文章 · 获赞 14 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/s15100007883/article/details/101207442