You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断字段或属性初始化完成?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 09:24:18