Unity WebGL平台 通过 URL 加载图片(UGUI RawImage / 模型材质)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

WebGL 必须用 UnityWebRequestTexture.GetTexture ,旧版 WWW 不推荐;最大坑:浏览器跨域 CORS,本地直接打开 index.html 会跨域报错,要用 web 服务(nginx/python http.server)打开。


提示:以下是本篇文章正文内容,下面案例可供参考

一、完整协程代码(推荐)

亲测可用:

复制代码
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class LoadUrlImage : MonoBehaviour
{
    public RawImage rawImage; // UGUI RawImage
    public Renderer planeRenderer; // 3D模型材质

    void Start()
    {
        // 远程图片地址
        string url = "https://xxx/test.jpg";
        StartCoroutine(LoadImageCoroutine(url));
    }

    IEnumerator LoadImageCoroutine(string url)
    {
        // 专门下载贴图,WebGL优化
        using (UnityWebRequest req = UnityWebRequestTexture.GetTexture(url))
        {
            yield return req.SendWebRequest();

            if (req.result == UnityWebRequest.Result.Success)
            {
                // 获取纹理
                Texture2D tex = DownloadHandlerTexture.GetContent(req);

                // 赋值给UGUI RawImage
                if(rawImage != null)
                {
                    rawImage.texture = tex;
                }
                // 赋值给模型材质
                if(planeRenderer != null)
                {
                    planeRenderer.material.mainTexture = tex;
                }
            }
            else
            {
                Debug.LogError($"加载失败:{req.error} code:{req.responseCode}");
            }
        }
    }
}

如果你需要 Sprite(UGUI Image 组件,不是 RawImage)

javascript 复制代码
// 在成功拿到tex之后
Sprite sprite = Sprite.Create(tex, new Rect(0,0,tex.width,tex.height), new Vector2(0.5f,0.5f));
GetComponent<Image>().sprite = sprite;

备选方案:下载二进制 bytes 再 LoadImage(兼容特殊场景)

下面展示一些 内联代码片

复制代码
IEnumerator LoadImageByBytes(string url)
{
    using var req = UnityWebRequest.Get(url);
    req.downloadHandler = new DownloadHandlerBuffer();
    yield return req.SendWebRequest();
    if(req.result == UnityWebRequest.Result.Success)
    {
        byte[] data = req.downloadHandler.data;
        Texture2D tex = new Texture2D(2,2);
        tex.LoadImage(data);
        rawImage.texture = tex;
    }
}

二、Unity WebGL 批量加载网络图片(带队列,限制并发)

特性:控制最大并发数量、加载成功 / 失败回调、加载进度、自动释放旧贴图,适配 WebGL;同样使用 UnityWebRequestTexture.GetTexture

代码如下(示例):

c 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class WebImageLoader : MonoBehaviour
{
    [Header("最大并发请求数量")]
    public int maxConcurrent = 2;
    
    // 等待加载队列
    private Queue<string> loadQueue = new Queue<string>();
    // 当前正在请求的数量
    private int activeCount;

    /// <summary>
    /// 图片加载回调
    /// </summary>
    public delegate void LoadCallback(Texture2D tex, string url, bool success);
    
    /// <summary>
    /// 添加图片到加载队列
    /// </summary>
    public void EnqueueLoad(string url, LoadCallback callback)
    {
        loadQueue.Enqueue(url);
        // 尝试启动下一个任务
        TryStartNext();
    }

    private void TryStartNext()
    {
        if (activeCount >= maxConcurrent || loadQueue.Count == 0)
            return;

        string url = loadQueue.Dequeue();
        activeCount++;
        StartCoroutine(LoadImageCoroutine(url, (tex, u, ok) =>
        {
            activeCount--;
            callback?.Invoke(tex, u, ok);
            // 继续消费队列
            TryStartNext();
        }));
    }

    private IEnumerator LoadImageCoroutine(string url, LoadCallback callback)
    {
        using (UnityWebRequest req = UnityWebRequestTexture.GetTexture(url))
        {
            yield return req.SendWebRequest();

            if (req.result == UnityWebRequest.Result.Success)
            {
                Texture2D tex = DownloadHandlerTexture.GetContent(req);
                callback.Invoke(tex, url, true);
            }
            else
            {
                Debug.LogError($"图片加载失败 {url} : {req.error}");
                callback.Invoke(null, url, false);
            }
        }
    }

    // 示例调用
    [ContextMenu("测试批量加载")]
    public void TestBatchLoad()
    {
        var urls = new List<string>()
        {
            "https://xxx/1.png",
            "https://xxx/2.png",
            "https://xxx/3.png",
            "https://xxx/4.png"
        };

        foreach (var u in urls)
        {
            EnqueueLoad(u, (tex, url, success) =>
            {
                if (success)
                {
                    Debug.Log($"加载完成:{url}, 贴图尺寸:{tex.width}x{tex.height}");
                    // rawImage.texture = tex;
                    // material.mainTexture = tex;
                }
            });
        }
    }
}

WebGL 重点注意事项

调试技巧:WebGL 打包后,F12 打开浏览器控制台,看 Network 面板,检查图片请求是否有 CORS 报错、404、403

内存管理 :贴图用完如果不再使用,调用 Destroy(tex),WebGL 内存不会自动回收,多图加载容易内存暴涨。Texture2D 不会自动 GC,频繁加载要手动 Destroy (tex)

相关推荐
阿松爱学习1 天前
【Unity开发】FileStream 详解及用法指南
unity·c#·unity开发
想做后端的前端1 天前
Unity-UIGI优化Rebatch与Rebuild
unity
玖玥拾1 天前
Unity Shader 基础与图形学(一)
unity·图形渲染·图形学·shader
百里香酚兰2 天前
【Unity学习笔记】如何把粉色Prefab还原
笔记·学习·unity
xcLeigh2 天前
Unity基础:使用Transform控制物体旋转——Rotate与LookAt详解
unity·教程·transform·rotate·lookat
平行云2 天前
3D应用推流太贵太慢?ImmerShare Lite:利用本地算力实现极简一键分享
unity·ue5·实时云渲染·云桌面·像素流·云游戏·串流
淡海水2 天前
11-04-Unity-Span-foreach-LINQ的分配与热路径边界
unity·c#·linq·foreach·span
灸木3 天前
Unity 多线程与并发:什么时候该用多线程?
unity
淡海水3 天前
11-02-Unity-Mono-vs-IL2CPP-两种脚本后端的数据结构行为差异
数据结构·unity·游戏引擎·il2cpp·mono