如何判断字段或属性初始化完成?Unity脚本依赖求替代方案
可行的解决方案
1. 回调函数机制
在One类里定义初始化完成的回调委托,初始化结束后触发回调,Two类订阅这个回调,收到通知再执行操作。
修改后的One类:
using UnityEngine; using System.Collections.Generic; public class One : MonoBehaviour { private List<string> _assetBundleList; // 定义回调委托 public System.Action OnInitializeCompleted; private void Start() { InitializeList(); } private void InitializeList() { // 模拟AssetBundle列表初始化逻辑 _assetBundleList = new List<string> { "bundle1", "bundle2" }; // 初始化完成后触发回调 OnInitializeCompleted?.Invoke(); } public IEnumerator<string> GetEnumerator() { return _assetBundleList.GetEnumerator(); } }
Two类修改:
public class Two : MonoBehaviour { public GameObject gameObjectWithScriptOne; private One _scriptOne; private void Start() { _scriptOne = gameObjectWithScriptOne.GetComponent<One>(); // 订阅初始化完成的回调 _scriptOne.OnInitializeCompleted += DoSomething; } private void DoSomething() { foreach(var assetBundle in _scriptOne) { Debug.Log($"加载AssetBundle: {assetBundle}"); } } // 记得取消订阅,避免内存泄漏 private void OnDestroy() { if (_scriptOne != null) { _scriptOne.OnInitializeCompleted -= DoSomething; } } }
2. 协程等待标记位
在One类里加一个布尔标记位表示初始化状态,Two类用协程循环检查这个标记,直到初始化完成再执行操作。
One类修改:
using UnityEngine; using System.Collections.Generic; public class One : MonoBehaviour { private List<string> _assetBundleList; // 公开的初始化完成标记 public bool IsInitialized { get; private set; } private void Start() { InitializeList(); } private void InitializeList() { // 模拟初始化操作(比如从本地/网络加载列表) _assetBundleList = new List<string> { "bundle1", "bundle2" }; IsInitialized = true; } public IEnumerator<string> GetEnumerator() { return _assetBundleList.GetEnumerator(); } }
Two类修改:
public class Two : MonoBehaviour { public GameObject gameObjectWithScriptOne; private One _scriptOne; private void Start() { _scriptOne = gameObjectWithScriptOne.GetComponent<One>(); // 启动协程等待初始化完成 StartCoroutine(WaitForInitializationThenDoSomething()); } private IEnumerator WaitForInitializationThenDoSomething() { // 循环等待直到初始化完成 while (!_scriptOne.IsInitialized) { yield return null; // 等待下一帧 } DoSomething(); } private void DoSomething() { foreach(var assetBundle in _scriptOne) { Debug.Log($"加载AssetBundle: {assetBundle}"); } } }
3. UnityEvent事件系统
用Unity自带的UnityEvent实现通知,好处是可以直接在Inspector面板绑定回调,不需要写代码订阅。
One类修改:
using UnityEngine; using System.Collections.Generic; using UnityEngine.Events; public class One : MonoBehaviour { private List<string> _assetBundleList; // 定义UnityEvent public UnityEvent OnInitializeDone; private void Start() { InitializeList(); } private void InitializeList() { _assetBundleList = new List<string> { "bundle1", "bundle2" }; // 触发事件 OnInitializeDone?.Invoke(); } public IEnumerator<string> GetEnumerator() { return _assetBundleList.GetEnumerator(); } }
Two类修改:
public class Two : MonoBehaviour { public GameObject gameObjectWithScriptOne; private One _scriptOne; private void Start() { _scriptOne = gameObjectWithScriptOne.GetComponent<One>(); // 代码绑定回调,也可以在Inspector里直接拖入绑定 _scriptOne.OnInitializeDone.AddListener(DoSomething); } public void DoSomething() { foreach(var assetBundle in _scriptOne) { Debug.Log($"加载AssetBundle: {assetBundle}"); } } private void OnDestroy() { if (_scriptOne != null) { _scriptOne.OnInitializeDone.RemoveListener(DoSomething); } } }
4. 异步Task等待
Unity 2017及以上版本支持Task异步操作,用这种方式可以更简洁地实现等待逻辑。
One类修改:
using UnityEngine; using System.Collections.Generic; using System.Threading.Tasks; public class One : MonoBehaviour { private List<string> _assetBundleList; private Task _initTask; private void Start() { _initTask = InitializeListAsync(); } private async Task InitializeListAsync() { // 模拟异步操作,比如等待网络请求完成 await Task.Delay(1000); _assetBundleList = new List<string> { "bundle1", "bundle2" }; } // 公开方法让外部等待初始化完成 public Task WaitForInitialization() { return _initTask; } public IEnumerator<string> GetEnumerator() { return _assetBundleList.GetEnumerator(); } }
Two类修改:
using UnityEngine; using System.Threading.Tasks; public class Two : MonoBehaviour { public GameObject gameObjectWithScriptOne; private One _scriptOne; private async void Start() { _scriptOne = gameObjectWithScriptOne.GetComponent<One>(); // 等待One的初始化完成 await _scriptOne.WaitForInitialization(); DoSomething(); } private void DoSomething() { foreach(var assetBundle in _scriptOne) { Debug.Log($"加载AssetBundle: {assetBundle}"); } } }
内容的提问来源于stack exchange,提问作者Shao Zhao
相关产品推荐
相关产品推荐

