如何在统一图像预制中显示图像,其链接存储在数组中

时间:2019-01-17 05:49:27

标签: c# unity3d

我正在统一开发一个应用程序,它将显示数据库中项目的名称和图像。我使用预制件来显示名称和图像,但是我不知道如何通过URL(链接)数组在预制件中显示图像。

我做了预制

newObj.transform.GetChild(2).GetComponent<Image>().sprite = GetItems.getItems.itemsimage[i];

统一显示图像,但我不知道如何显示

public void PopulateItems(int categoryBtnClick)
{
    GameObject newObj;
    for (int i = 0; i < GetItems.getItems.itemsData.Length-1; i++)
    {
        int cat_id = int.Parse(GetItems.getItems.category_id[i]);
         if (cat_id == categoryBtnClick) //cat_id and categoryBtnClick contains id of item
         {
             newObj = (GameObject)Instantiate(itemScrollviewPrefab, transform);
             newObj.transform.GetChild(0).GetComponent<Text>().text =GetItems.getItems.itemsName[i];
             newObj.transform.GetChild(1).GetComponent<Text>().text = GetItems.getItems.itemsId[i];
             if (GetItems.getItems.itemsModel[i] != null)
             {
                 newObj.transform.GetChild(2).GetComponent<Image>().sprite =GetItems.getItems.itemsimage[i] ; //itemsimage[i] contains link of image
             }
             newObj.transform.GetChild(3).GetComponent<Text>().text = GetItems.getItems.itemsPrice[i];
             newObj.transform.GetChild(4).GetComponent<Text>().text = GetItems.getItems.itemsDescription[i];
             newObj.transform.parent = itemContentParent.transform; 
         }
     }
}

我希望每次循环在该索引上运行图像都会统一打印

1 个答案:

答案 0 :(得分:0)

RawImage没有sprite,但是需要Texture

您不能简单地传递URL。您必须download the texture,然后将结果应用于rawImage.texture。来自文档的示例:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class MyBehaviour : MonoBehaviour 
{
    void Start() 
    {
        StartCoroutine(GetTexture());
    }

    IEnumerator GetTexture() 
    {
        UnityWebRequest www = UnityWebRequestTexture.GetTexture("http://www.my-server.com/image.png");
        yield return www.SendWebRequest();

        if(www.isNetworkError || www.isHttpError) 
        {
            Debug.Log(www.error);
        }
        else 
        {
            Texture myTexture = ((DownloadHandlerTexture)www.downloadHandler).texture;
        }
    }
}

下载是异步进行的,因此在下载所有图像之前可能会生成预制件...取决于您如何处理此问题(例如,同时显示加载动画或占位符)-我假设您要实例化马上。

您只需将回调添加到download方法即可在成功或失败时执行任何方法:

IEnumerator GetTexture(string url, Action<Texture> successCallback, = null, Action<string> errorCallback = null) 
{
    UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
    yield return www.SendWebRequest();

    if(www.isNetworkError || www.isHttpError) 
    {
        errorCallback?.Invoke(www.error);
    }
    else 
    {
        successCallback?.Invoke(((DownloadHandlerTexture)www.downloadHandler).texture);
    }
}

,然后在代码中添加回调,例如使用lambda expressions,应在成功或错误时执行:

// ...

if (GetItems.getItems.itemsModel[i] != null)
{
    // optional here add a loading or default texture 
    // to be displayed until texture is downloaded e.g.
    newObj.transform.GetChild(2).GetComponent<RawImage>().texture = someDefaultTexture;                         

    // start the download
    StartCoroutine(GetTexture(
        // The url
        GetItems.getItems.itemsimage[i],

        // executed on success
        (s) => 
        {
            OnSuccess(newObj.transform.GetChild(2).GetComponent<RawImage>(), s);
        },

        // optional for visualizing download errors
        (e) =>
        {
            OnError(e);
        }
    ));
}

// ...

最后实现回调,例如:

// callback for success download
private void OnSuccess(RawImage rawImage, Texture texture)
{
    rawImage.texture = texture;
}

// callback for download error
private void OnError(RawImage rawImage, string error)
{
    rawImage.Texture = someErrorTexture;
    Debug.Log(error, this);
}

关于下载的纹理的一个警告(因为我最近也犯了这个错误):

通常未使用/未引用的纹理会被垃圾收集/删除,因此设备的内存不会被填满... 但是显然,通过UnityWebRequest创建的纹理甚至不会被破坏如果他们没有任何参考资料了。

这可能会导致内存泄漏,导致下载的纹理填充设备的内存!

因此,当您不再需要任何下载的纹理时,请确保积极销毁它们,例如通过添加类似

的脚本
public class CleanUpTexture : MonoBehaviour
{
    private RawImage rawImage;

    private void Awake()
    {
        rawImage = GetComponent<RawImage>();
    }

    private void OnDestroy()
    {
        if(!rawImage || rawImage.texture == null) return;

        Destroy(rawImage.texture);
    }
}

RawImage组件旁边的那个纹理是否应该与对象一起被破坏。

这当然假设您永远不会将相同的纹理分配给其他任何东西。并且还假设您永远不会为该对象分配不同的纹理(因为1.您会松散对下载的纹理的引用,并且2.可能会破坏您本来不是想要的纹理)