Unity动态载入多个图片到Image(UI)的方法的探讨

需要载入大量图片到Image并显示,基本方法有2种,用WWW或者c#的FileStream。考虑到协程,异步,以及把代码统一写或者分开写,衍生出5、6种方法。

job system只能处理值类型,帮不上忙。ecs也主要集中在处理update里面的内容,似乎也不使用。还考虑过多线程,这里不是很确定。unity多线程过程中,子线程不能使用unity的api,就只能用c#把文件读取过程加速,对多线程不熟,就放弃了。

结论

会出现3种效果,在使用FileStream异步,在统一的地方写代码适应毕竟广。

测试方法,加载102张512*512分辨率的图片,显示成一个图片下拉列表,样子如下

测试视频地址(好像没啥意义):https://www.bilibili.com/video/av32416457/

方法一、统一调用WWW协程

GuiController.CS

    /// <summary>
    /// 统一处理WWW协程载入
    /// </summary>
    public void UniteCoroutineWWW()
    {
        //从json获取图片地址信息并转为对象数组
        MediaText[] mts = JsonConvert.DeserializeObject<MediaText[]>(ifJson.text);
        scrollView.SetActive(true);

        //遍历对象数组
        foreach (MediaText mt in mts)
        {
            //实列化游戏对象
            Transform tf = Instantiate(prefab, content);
            tf.GetChild(1).GetComponent<Text>().text = mt.Name;
            tf.GetChild(2).GetComponent<Text>().text = mt.Description;
            Image image = tf.GetChild(0).GetComponent<Image>();

            //调用协程
            StartCoroutine(LoadByWWW(mt.Icon, image));
        }
    }

    /// <summary>
    /// WWW协程载入图片
    /// </summary>
    /// <param name="path">图片地址</param>
    /// <param name="image">Image对象</param>
    /// <returns></returns>
    IEnumerator LoadByWWW(string path, Image image)
    {
        path = @"file://"+fileRoot + path;

        using (WWW www = new WWW(path))
        {
            yield return www;
            if (www.isDone && www.error == null)
            {
                image.sprite = Sprite.Create(www.texture, new Rect(0, 0, 512f, 512f), new Vector2(0.5f, 0.5f));
            }
            else
            {
                Debug.Log(www.error);
            }
        }
    }

载入情况:先把所有Image初始完成后,统一载入了图片。

cpu占用信息

600

方法二、统一调用WWW载入,不使用协程

GuiController.CS

    /// <summary>
    /// 统一调用WWW,不使用协程
    /// </summary>
    public void UniteSynchronizeWWW()
    {
        string path = @"file://"+fileRoot;
        MediaText[] mts = JsonConvert.DeserializeObject<MediaText[]>(ifJson.text);
        scrollView.SetActive(true);
        foreach (MediaText mt in mts)
        {
            Transform tf = Instantiate(prefab, content);
            tf.GetChild(1).GetComponent<Text>().text = mt.Name;
            tf.GetChild(2).GetComponent<Text>().text = mt.Description;
            Image image = tf.GetChild(0).GetComponent<Image>();

            using (WWW www = new WWW(path+mt.Icon))
            {
                while (!www.isDone)
                {
                    if (www.error == null)
                    {
                        image.sprite = Sprite.Create(www.texture, new Rect(0, 0, 512f, 512f), new Vector2(0.5f, 0.5f));
                    }
                    else
                    {
                        Debug.Log(www.error);
                    }
                }
            }
        }
}

载入情况,会等所有内容准备好后一并显示

cpu占用信息

方法三、统一FileStream异步

GuiController.CS

   /// <summary>
    /// 异步载入图片
    /// </summary>
    /// <param name="path">路径</param>
    /// <param name="image">Image对象</param>
    /// <returns></returns>
    async Task LoadByFSAsync(string path, Image image)
    {
        path = fileRoot + path;
        byte[] result;

        using (FileStream SourceStream = File.Open(path, FileMode.Open))
        {
            result = new byte[SourceStream.Length];
            await SourceStream.ReadAsync(result, 0, (int)SourceStream.Length);
        }

        Texture2D tx = new Texture2D(512, 512);
        tx.LoadImage(result);
        image.sprite = Sprite.Create(tx, new Rect(0, 0, 512f, 512f), new Vector2(0.5f, 0.5f));
    }

    /// <summary>
    /// 统一异步载入
    /// </summary>
    public async void UniteFSAsync()
    {
        MediaText[] mts = JsonConvert.DeserializeObject<MediaText[]>(ifJson.text);
        scrollView.SetActive(true);
        foreach (MediaText mt in mts)
        {
            Transform tf = Instantiate(prefab, content);
            tf.GetChild(1).GetComponent<Text>().text = mt.Name;
            tf.GetChild(2).GetComponent<Text>().text = mt.Description;
            Image image = tf.GetChild(0).GetComponent<Image>();

            await LoadByFSAsync(mt.Icon, image);
        }
}

载入情况:会顺序将对象实例化并载入图片

cpu占用

方法四、由游戏对象自己用WWW协程载入

GuiController.CS

    /// <summary>
    /// 由游戏对象自己载入图片
    /// </summary>
    public void SelfLoad()
    {
        MediaText[] mts = JsonConvert.DeserializeObject<MediaText[]>(ifJson.text);
        scrollView.SetActive(true);
        foreach (MediaText mt in mts)
        {
            Transform tf = Instantiate(prefab, content);
            tf.GetChild(1).GetComponent<Text>().text = mt.Name;
            tf.GetChild(2).GetComponent<Text>().text = mt.Description;
            LoadImage loadImage = tf.GetComponent<LoadImage>();
            loadImage.path = fileRoot + mt.Icon;
            //LoadImageDestory lid = tf.GetComponent<LoadImageDestory>();
            //lid.path = fileRoot + mt.Icon;
        }
}

LoadImage.CS

	void Start () {
        image = transform.GetChild(0).GetComponent<Image>();
        StartCoroutine(LoadByWWW(path, image)); 
        //LoadByFSAsync(path, image); 
    }

    /// <summary>
    /// 用WWW协程载入图片
    /// </summary>
    /// <param name="path"></param>
    /// <param name="image"></param>
    /// <returns></returns>
    IEnumerator LoadByWWW(string path, Image image)
    {
        path = @"file://" + path;
        using (WWW www = new WWW(path))
        {
            yield return www;
            if (www.isDone && www.error == null)
            {
                image.sprite = Sprite.Create(www.texture, new Rect(0, 0, 512f, 512f), new Vector2(0.5f, 0.5f));
            }
            else
            {
                Debug.Log(www.error);
            }
        }
    }

载入情况:先把所有Image初始完成后,统一载入了图片。

cpu占用

方法五,由游戏对象自己用FileStream异步载入

GuiController.CS

    /// <summary>
    /// 由游戏对象自己载入图片
    /// </summary>
    public void SelfLoad()
    {
        MediaText[] mts = JsonConvert.DeserializeObject<MediaText[]>(ifJson.text);
        scrollView.SetActive(true);
        foreach (MediaText mt in mts)
        {
            Transform tf = Instantiate(prefab, content);
            tf.GetChild(1).GetComponent<Text>().text = mt.Name;
            tf.GetChild(2).GetComponent<Text>().text = mt.Description;
            LoadImage loadImage = tf.GetComponent<LoadImage>();
            loadImage.path = fileRoot + mt.Icon;
            //LoadImageDestory lid = tf.GetComponent<LoadImageDestory>();
            //lid.path = fileRoot + mt.Icon;
        }
}

LoadImage.CS

	void Start () {
        image = transform.GetChild(0).GetComponent<Image>();
        //StartCoroutine(LoadByWWW(path, image)); 
        LoadByFSAsync(path, image); 
    }

    async Task LoadByFSAsync(string path, Image image)
    {
        byte[] result;

        using (FileStream SourceStream = File.Open(path, FileMode.Open))
        {
            result = new byte[SourceStream.Length];
            await SourceStream.ReadAsync(result, 0, (int)SourceStream.Length);
        }

        Texture2D tx = new Texture2D(512, 512);
        tx.LoadImage(result);
        image.sprite = Sprite.Create(tx, new Rect(0, 0, 512f, 512f), new Vector2(0.5f, 0.5f));
    }

载入情况,会等所有内容准备好后一并显示

cpu占用信息

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值