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

Unity中使用LoadImage加载图片卡顿,如何实现无阻塞加载?

Unity加载本地图片避免卡顿的最佳方案

你的代码卡顿的核心原因是所有操作都在主线程同步执行:File.ReadAllBytes会阻塞主线程读取文件,texture.LoadImage也会在主线程处理图片解码,大图片必然导致卡顿。以下是几种可靠的异步加载方案:

方案一:使用UnityWebRequestTexture(官方推荐,简单高效)

UnityWebRequestTexture内部会在后台线程处理文件读取和纹理解码,完全不会阻塞主线程,是处理本地/远程图片异步加载的首选方式。

// 异步加载本地图片的协程方法
public IEnumerator LoadTextureAsync(string localFilePath, Action<Texture2D> onLoadComplete)
{
    // 把本地路径转换为UnityWebRequest支持的file://协议格式
    string requestUrl = "file://" + localFilePath;
    // 处理Windows系统下的路径分隔符
    requestUrl = requestUrl.Replace("\\", "/");

    using (UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(requestUrl))
    {
        // 发送异步请求,等待完成
        yield return webRequest.SendWebRequest();

        if (webRequest.result == UnityWebRequest.Result.Success)
        {
            // 获取加载完成的纹理
            Texture2D loadedTexture = DownloadHandlerTexture.GetContent(webRequest);
            onLoadComplete?.Invoke(loadedTexture);
        }
        else
        {
            Debug.LogError($"图片加载失败: {webRequest.error}");
            onLoadComplete?.Invoke(null);
        }
    }
}

调用示例

// 在需要加载图片的地方启动协程
StartCoroutine(LoadTextureAsync("你的本地图片路径", (texture) => {
    if (texture != null)
    {
        // 在这里使用纹理,比如赋值给UI的RawImage
        yourRawImage.texture = texture;
    }
}));

方案二:后台线程读文件+主线程加载纹理

如果需要更精细控制流程,可以把文件读取的耗时操作放到后台线程,仅在主线程执行纹理解码(因为Unity的Texture操作必须在主线程)。

// 后台加载图片的方法
public void LoadTextureInBackground(string localFilePath, Action<Texture2D> onLoadComplete)
{
    // 把文件读取任务放到线程池
    System.Threading.ThreadPool.QueueUserWorkItem(_ => {
        byte[] imageBytes = null;
        try
        {
            imageBytes = File.ReadAllBytes(localFilePath);
        }
        catch (Exception ex)
        {
            Debug.LogError($"读取文件失败: {ex.Message}");
        }

        // 回到主线程处理纹理加载
        UnityMainThreadDispatcher.Instance.Enqueue(() => {
            if (imageBytes == null)
            {
                onLoadComplete?.Invoke(null);
                return;
            }

            Texture2D texture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
            if (texture.LoadImage(imageBytes))
            {
                onLoadComplete?.Invoke(texture);
            }
            else
            {
                Debug.LogError("纹理解码失败");
                Destroy(texture);
                onLoadComplete?.Invoke(null);
            }
        });
    });
}

配套主线程调度器

需要一个简单的工具类来把回调切回主线程:

public class UnityMainThreadDispatcher : MonoBehaviour
{
    public static UnityMainThreadDispatcher Instance { get; private set; }
    private readonly Queue<Action> _pendingActions = new Queue<Action>();
    private readonly object _lockObj = new object();

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void Update()
    {
        lock (_lockObj)
        {
            while (_pendingActions.Count > 0)
            {
                _pendingActions.Dequeue()();
            }
        }
    }

    public void Enqueue(Action action)
    {
        lock (_lockObj)
        {
            _pendingActions.Enqueue(action);
        }
    }
}

方案三:Addressables资源系统(大型项目首选)

如果是资源量较大的项目,推荐使用Unity官方的Addressables系统,它不仅支持异步加载,还能统一管理资源的缓存、卸载、更新,大幅简化资源管理流程。

加载示例

using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public async void LoadTextureWithAddressables(string assetKey)
{
    try
    {
        AsyncOperationHandle<Texture2D> loadHandle = Addressables.LoadAssetAsync<Texture2D>(assetKey);
        Texture2D texture = await loadHandle.Task;
        
        // 使用纹理
        yourRawImage.texture = texture;
        
        // 不需要时可以释放资源(可选)
        // Addressables.Release(loadHandle);
    }
    catch (Exception ex)
    {
        Debug.LogError($"Addressables加载失败: {ex.Message}");
    }
}

最佳实践总结

  • 中小图片或快速迭代场景:优先用UnityWebRequestTexture,代码简单且无需额外依赖
  • 需要精细控制线程流程:用后台线程读文件+主线程加载纹理的组合
  • 大型项目或需要复杂资源管理:用Addressables统一管理资源

内容的提问来源于stack exchange,提问作者Esa Nuriana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:50:41