Unity打开项目时如何仅执行一次脚本 避免停止播放后重复触发
问题根因
原代码重复执行的核心原因是Unity默认开启*域重载(Domain Reload)*机制:每次进入/退出播放模式、脚本编译完成时,编辑器会重置所有脚本的运行时状态,重新执行所有标记[InitializeOnLoad]类的静态构造函数,原逻辑没有跨域的状态标记,会重复把初始化逻辑绑定到EditorApplication.update回调上,导致每次退出播放模式后面板重复弹出。
修复实现
用Unity提供的SessionState做会话级标记即可解决问题,该存储的生命周期和当前编辑器打开项目的会话绑定,不会因为域重载、脚本编译丢失数据,关闭编辑器/切换项目时自动重置,完全匹配「仅项目打开加载时执行一次」的需求。
using UnityEditor; [InitializeOnLoad] public class PackageInitAutorun { private const string InitDoneFlag = "CustomPackage_InitPanelExecuted"; static PackageInitAutorun() { // 本次会话已经执行过初始化,直接跳过 if (SessionState.GetBool(InitDoneFlag, false)) return; EditorApplication.update += RunOnceOnProjectLoad; } private static void RunOnceOnProjectLoad() { EditorApplication.update -= RunOnceOnProjectLoad; // 写入会话标记,后续域重载不会再触发初始化逻辑 SessionState.SetBool(InitDoneFlag, true); // 自定义初始化面板逻辑 Panel.Init(); } }
注意事项
- 不要用普通静态变量做执行标记:静态变量会在域重载时被重置,无法跨域保留状态,和原方案一样会出现重复执行问题
- 不要用
EditorPrefs做标记:EditorPrefs数据会持久化到本地磁盘,下次启动Unity打开项目时标记仍然存在,会导致初始化面板永远不弹出 - 如果关闭了Unity的域重载功能(Enter Play Mode Options里禁用Reload Domain),该方案依然可以正常工作
内容的提问来源于stack exchange,提问作者KiynL
相关产品推荐
相关产品推荐

