Unity场景中图片每次加载顺序不一致的问题求助
解决Unity异步下载图片显示顺序混乱的问题
我来帮你搞定这个图片顺序乱跳的问题~
问题原因
你的代码里每个图片都是通过异步网络请求下载的,而网络请求的完成时间是不确定的——比如第0张图片可能因为网络延迟最后下载完成,它就会被最后实例化出来,导致显示顺序和你期望的photolist顺序不一致。虽然你给每个图片命名加了index,但实例化的顺序完全由请求返回的速度决定,自然每次进入场景顺序都不一样。
解决方案:固定占位,异步填充
最直观友好的解决方式是先按固定顺序创建所有图片的占位容器,等图片下载完成后再把纹理赋值给对应位置的占位。这样不管下载速度快慢,图片的位置从一开始就是固定的,下载完成后只是填充内容而已。
修改后的代码如下:
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ImageDownloader : MonoBehaviour { public GameObject contentRef; public RawImage imgPrefab; // 存储按顺序创建的图片占位,用于后续赋值纹理 private List<RawImage> _imagePlaceholders = new List<RawImage>(); void Start() { DownloadtheFiles(); } public void DownloadtheFiles() { List<string> photolist = ES2.LoadList<string>("myPhotos.txt"); // 第一步:先按photolist的顺序创建所有图片占位 for (int i = 0; i < photolist.Count; i++) { RawImage placeholder = Instantiate(imgPrefab, contentRef.transform); placeholder.name = "Image-" + i; _imagePlaceholders.Add(placeholder); // 可选:给占位设置一张加载中的默认图,提升用户体验 // placeholder.texture = Resources.Load<Texture2D>("LoadingPlaceholder"); } // 第二步:开始异步下载图片 for (int i = 0; i < photolist.Count; i++) { // 捕获当前循环的index,避免闭包陷阱 int index = i; new GetUploadedRequest() .SetUploadId(photolist[index]) .Send((response) => { StartCoroutine(DownloadImages(response.Url, index)); }); } } public IEnumerator DownloadImages(string downloadUrl, int index) { var www = new WWW(downloadUrl); yield return www; // 加载下载到的图片纹理 Texture2D tex = new Texture2D(4, 4); www.LoadImageIntoTexture(tex); // 直接给对应index的占位图片赋值纹理 _imagePlaceholders[index].texture = tex; } }
另一种方案:全部下载完成后再按顺序实例化
如果你的需求是等所有图片都下载完成后再一次性显示,可以用字典存储下载好的纹理,等全部完成后按index排序再实例化:
using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; public class ImageDownloader : MonoBehaviour { public GameObject contentRef; public RawImage imgPrefab; // 存储下载完成的纹理,key是index private Dictionary<int, Texture2D> _loadedTextures = new Dictionary<int, Texture2D>(); private int _totalImageCount; void Start() { DownloadtheFiles(); } public void DownloadtheFiles() { List<string> photolist = ES2.LoadList<string>("myPhotos.txt"); _totalImageCount = photolist.Count; for (int i = 0; i < photolist.Count; i++) { int index = i; new GetUploadedRequest() .SetUploadId(photolist[index]) .Send((response) => { StartCoroutine(DownloadImages(response.Url, index)); }); } } public IEnumerator DownloadImages(string downloadUrl, int index) { var www = new WWW(downloadUrl); yield return www; Texture2D tex = new Texture2D(4, 4); www.LoadImageIntoTexture(tex); _loadedTextures[index] = tex; // 检查是否所有图片都已下载完成 if (_loadedTextures.Count == _totalImageCount) { // 按index排序后依次实例化 var sortedTextures = _loadedTextures.OrderBy(kv => kv.Key); foreach (var texturePair in sortedTextures) { RawImage newImg = Instantiate(imgPrefab, contentRef.transform); newImg.name = "Image-" + texturePair.Key; newImg.texture = texturePair.Value; } } } }
补充说明
如果你的contentRef使用了VerticalLayoutGroup或HorizontalLayoutGroup这类布局组件,第一种方案的占位会自动按创建顺序排列,完全符合你的需求;第二种方案适合需要避免加载过程中图片逐个弹出的场景。
附上你提供的两次场景截图:
第一次进入场景的图片顺序:
第二次进入场景的图片顺序:
内容的提问来源于stack exchange,提问作者Angelsm
相关产品推荐
相关产品推荐

