推荐阅读
大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
首先,来了解一下事件函数的执行顺序,下图是官方给的脚本中事件函数的执行顺序:

众所周知,Unity中某个脚本的事件函数执行顺序是Awake、Start、Update、LateUpdate等,那么不同脚本之间的事件函数的调用顺序是怎么样的呢,以及如何控制不同脚本之间的事件函数的调用顺序呢?
看完这篇文章你就能找到答案。
.meta文件
看似每个脚本之间的调用顺序是随机的,其实是有迹可循的。
痕迹就在于生成.cs文件后同步生成的.cs.meta文件:
打开.cs.meta文件:
executionOrder: 0 这个就是执行顺序。
越小执行的优先级越高。
默认的情况下就是0。若想让脚本最先执行,可以把它设置为负值。
既然知道了脚本的执行顺序,那么怎么控制脚本的执行顺序呢。
直接打开脚本的.meta文件,然后修改executionOrder的值。
越小执行的优先级越高。
在Unity中设置脚本的执行顺序:


在Project视图中随便找一个脚本,点击右上角Execution Order后弹出Project Settings视图,然后设置执行顺序即可。
脚本执行顺序工具类:
新建脚本命名为AttributeUtils.cs,双击打开脚本,编辑代码:
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.Reflection; // 定义属性类 管理相关的函数 [System.AttributeUsage(AttributeTargets.All)] public class SFHCall : Attribute { public SFHCall(int lev) { level = lev; } public int GetLevel() { return level; } protected int level; } // 定义属性类 设置函数的属性 [System.AttributeUsage(AttributeTargets.All)] public class SFHStartCall : SFHCall { public SFHStartCall(int lev) : base(lev) { level = lev; } } // 管理执行对象 public class AtrributeFlagFunction { public MonoBehaviour monob; public MethodInfo methodInfo; } // 属性工具类 public class AttributeUtils { // 使用字典来存储所有的相关函数 public static SortedList myFuctionList = new SortedList(); public static void GetAllDestByProperties<T>(object[] mono) where T : SFHCall { int length = mono.Length; for (int i = 0; i < length; i++) { Cache<T>((MonoBehaviour)mono[i]); } } private static void Cache<T>(MonoBehaviour p) where T : SFHCall { var type = p.GetType(); // 不会重复调用父类的方法了。 var fields2 = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (var field in fields2) { AtrributeFlagFunction aff = new AtrributeFlagFunction(); var objs = field.GetCustomAttributes(typeof(T), false); if (objs.Length > 0) { aff.monob = p; aff.methodInfo = field; T attr = (T)objs[0]; int value = attr.GetLevel(); if (!myFuctionList.ContainsKey(value)) { { List<AtrributeFlagFunction> AttributeList = new List<AtrributeFlagFunction>(); AttributeList.Add(aff); myFuctionList.Add(value, AttributeList); } } else { List<AtrributeFlagFunction> mlist = (List<AtrributeFlagFunction>)myFuctionList[value]; mlist.Add(aff); } } } } }csharp运行
这个脚本是用属性来获取所有的对象的函数,然后再去排列顺序去执行。
实例化属性管理工具类:
再新建脚本StartFromHere.cs,双击打开脚本,修改代码:
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEditor; using System.Reflection; public class StartFromHere : MonoBehaviour { void Start() { //初始化 获取所有的相关函数 并执行 InitialStart(); } private void InitialStart() { MonoBehaviour[] testMono = FindObjectsOfType<MonoBehaviour>(); AttributeUtils.GetAllDestByProperties<SFHStartCall>(testMono); for (int i = 0; i < AttributeUtils.myFuctionList.Count; i++) { List<AtrributeFlagFunction> mlist = (List<AtrributeFlagFunction>)AttributeUtils.myFuctionList.GetByIndex(i); for (int j = 0; j < mlist.Count; j++) { AtrributeFlagFunction item = mlist[j]; MonoBehaviour monob = item.monob; object result = item.methodInfo.Invoke((object)monob, new object[] { }); if (item.methodInfo.ReturnType == typeof(IEnumerator)) { monob.StartCoroutine((IEnumerator)result); } } } } }csharp运行
这个脚本就是实例化脚本执行顺序工具类,需要挂载在对象上。
使用方法:
新建三个脚本,随便命名,然后编辑代码:
public class SFHTest1 : MonoBehaviour { [SFHStartCall(1)] void OnStart() { Debug.Log("第一个执行"); } }csharp运行
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SFHTest2 : MonoBehaviour { [SFHStartCall(2)] void OnStart() { Debug.Log("第二个执行"); } }csharp运行
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SFHTest3 : MonoBehaviour { [SFHStartCall(3)] void OnStart() { Debug.Log("第三个执行"); } }csharp运行
SFHStartCall后面的参数就是执行顺序,越大越早执行,然后都挂载到对象上:
执行结果:
本篇文章实现了如何控制脚本执行的顺序。
最后使用了一个脚本执行顺序工具 类 来控制脚本的执行顺序。
你的点赞就是对博主的支持,有问题记得留言:
博主主页有联系方式。
博主还有跟多宝藏文章等待你的发掘哦:
| 专栏 | 方向 | 简介 |
|---|---|---|
| Unity3D开发小游戏 | 小游戏开发教程 | 分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。 |
| Unity3D从入门到进阶 | 入门 | 从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。 |
| Unity3D之UGUI | UGUI | Unity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。 |
| Unity3D之读取数据 | 文件读取 | 使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。 |
| Unity3D之数据集合 | 数据集合 | 数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。 |
| Unity3D之VR/AR(虚拟仿真)开发 | 虚拟仿真 | 总结博主工作常见的虚拟仿真需求进行案例讲解。 |
| Unity3D之插件 | 插件 | 主要分享在Unity开发中用到的一些插件使用方法,插件介绍等 |
| Unity3D之日常开发 | 日常记录 | 主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等 |
| Unity3D之日常BUG | 日常记录 | 记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。 |
Unity爱好者社区 分享Unity相关的技术文章、工具资源等。