提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、完整协程代码(推荐)
- [二、Unity WebGL 批量加载网络图片(带队列,限制并发)](#二、Unity WebGL 批量加载网络图片(带队列,限制并发))
- [WebGL 重点注意事项](#WebGL 重点注意事项)
前言
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)