Unity中从Firebase Storage批量下载图片并显示到不同对象的问题
问题:Firebase图片加载后仅显示在最后一个预制体面板
问题描述
通过Firestore获取服装数据并实例化预制体面板,字符串数据能正确显示,但所有Firebase Storage下载的图片仅显示在最后一个面板上,每个面板无法加载对应图片。
问题根源
核心原因是异步回调共享了类成员变量costImage:
- 在循环调用
SpawnWithImageTest时,每次都会将类成员costImage替换为当前新生成面板的RawImage引用。 - 由于
GetDownloadUrlAsync和后续的图片加载协程是异步操作,当这些异步任务完成时,costImage已经被覆盖为最后一次循环的面板引用,导致所有图片都被设置到最后一个面板上。
修复方案
将所有与当前面板绑定的控件变量改为局部变量,确保每个异步回调捕获的是当前面板的专属控件引用,避免被后续循环覆盖。
修正后的代码
修改后的SpawnWithImageTest方法
public void SpawnWithImageTest(string name, string franch, string size, int price, int waist, int chest) { GameObject child = Instantiate(CostumePrefab); child.transform.SetParent(PanelHolder.transform, false); GameObject NameReq = child.transform.Find("Panel").transform.Find("CostName").gameObject; GameObject FranchiseReq = child.transform.Find("Panel").transform.Find("Franch").gameObject; GameObject SizeReq = child.transform.Find("Panel").transform.Find("Size").gameObject; GameObject PriceReq = child.transform.Find("Panel").transform.Find("Price").gameObject; GameObject CostImage = child.transform.Find("RawImage").gameObject; // 使用局部变量存储当前面板的控件引用,替代类成员变量 TextMeshProUGUI reqName = NameReq.GetComponent<TextMeshProUGUI>(); TextMeshProUGUI reqFranchise = FranchiseReq.GetComponent<TextMeshProUGUI>(); TextMeshProUGUI reqSize = SizeReq.GetComponent<TextMeshProUGUI>(); TextMeshProUGUI reqPrice = PriceReq.GetComponent<TextMeshProUGUI>(); RawImage localCostImage = CostImage.GetComponent<RawImage>(); reqName.text = name; reqFranchise.text = franch; reqSize.text = string.Format("{0} (W: {1} C: {2}) ", size, waist.ToString(), chest.ToString()); reqPrice.text = price.ToString(); string filename = string.Format("{0}.jpeg", ConvertNameToFileName(name, storedata)); StorageReference imgcost = storageReference.Child(string.Format("uploads/{0}", filename)); // 捕获当前面板的局部RawImage引用,确保异步任务对应正确的面板 imgcost.GetDownloadUrlAsync().ContinueWithOnMainThread(task => { if(!task.IsFaulted && !task.IsCanceled) { StartCoroutine(LoadImage(System.Convert.ToString(task.Result), localCostImage)); } else { Debug.Log(task.Exception); } }); }
保留原LoadImage协程(无需修改)
IEnumerator LoadImage(string MediaUrl, RawImage img) { UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl); Debug.Log(MediaUrl); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.Log(request.error); } else { img.texture = ((DownloadHandlerTexture)request.downloadHandler).texture; } }
额外说明
- 若原类中的
ReqName、ReqFranchise等成员变量没有其他业务场景使用,建议直接删除,避免后续代码误用。 - 异步操作中捕获局部变量是Unity处理多实例异步加载的常用方案,能确保每个任务独立绑定对应的UI控件。
内容的提问来源于stack exchange,提问作者Hovanon
相关产品推荐
相关产品推荐

