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)

相关推荐
Martina_03213 天前
AI生成3D场景导入 Unity/Unreal 后,NPC 总串层?用6步检查导航高度与跨层连接
人工智能·游戏·数学建模·3d·unity·自然语言处理·aigc
小贺儿开发3 天前
Unity 局域网遥控幻灯片展示工具 3.0
科技·http·unity·工具·ppt·通信·网页
WarPigs5 天前
Unity对象不应该使用null传播的问题
unity
每日出拳老爷子6 天前
【VR】【Unity】抓走转放系列21|一天搭完门和抽屉工具槽:小场景按这个次序拼装
unity·vr·驱动·排错·snap zone
淡海水6 天前
02-02-原理篇-分代GC
算法·unity·c#·游戏引擎·.net·gc
小贺儿开发7 天前
Unity 文物新生 会讲故事的文物展墙
人工智能·科技·unity·ai·视频·互动·演示
淡海水7 天前
02-03-原理篇-大对象堆
unity·c#·游戏引擎·.net·gc
WarPigs8 天前
Unity在Create菜单添加创建自定义脚本模板选项
unity
淡海水8 天前
02-01-原理篇-Mark-Sweep与变种算法
算法·unity·c#·游戏引擎·.net·gc
babywang08 天前
Unity笔记--塔防游戏中的ECS架构:从原理到实战的全面解析
unity·ecs架构