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)

相关推荐
平行云4 小时前
建筑BIM/3D可视化轻量级实时评审与分享方案
unity·ue5·3dsmax·实时云渲染·云桌面·云游戏·建筑bim
2501_915106321 天前
Windows 上开发 Unity iOS,使用 KXBuild 进行真机调试、性能采样与打包 ipa
windows·vscode·unity·ios·个人开发·swift·敏捷流程
FFFFujige1 天前
【Unity】一个的Dots用Ruhanka踩坑记录
unity·游戏引擎
凯基迪科技2 天前
Unity游戏加密锁逆向方案、选型与攻防分析
游戏·unity·游戏引擎
阿松爱学习2 天前
【Unity开发】局部区域截图功能实现
unity·c#
淡海水2 天前
08-02-优化-LINQ与函数式编程的GC代价
unity·c#·.netcore·linq·gc
警醒与鞭策3 天前
Codex桌面版与Claude桌面版使用设置
android·unity·ai·性能优化
xcLeigh3 天前
Unity基础:Destroy与DestroyImmediate——正确销毁游戏物体的方式
游戏·unity·游戏引擎·教程
lllhhh_远方3 天前
unity中URP场景阴影锯齿严重解决方案
unity·游戏引擎
淡海水3 天前
07-06-源码-.NET Core GC的极致优化技术
unity·架构·c#·.netcore·gc·1024程序员节