Unity 异步加载图片

最近做项目处理实时接收数据,每条数据对应一张图片,为了提高性能,
先显示每条数据对应生成模型,然后将图片做好与模型的映射,然后再加上图片校验码和模型之间的校验码作比较
等待图片下载完毕后,会将图片准确无误的给对应的模型。
首先思路是
1.客户端接收 服务器发来的每条数据,其中数据中包含图片链接,客户端先
将模型给创建并显示,然后在模型上显示Loading加载(ugui可以做进度条)
2.将img url给放到队列中 ,每帧都会去检查当前开启协程的个数假定最多为30个,
不到30,就开启协程用www 下载图片 计数加1,直到协程数量为30,就等待其它协程释放,然
后继续从队列取数据下载。
3.www 下载完毕后,通知视图层接收图片,协程释放计数减1
最后代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using System.Net;

public struct ImageEvent
{
    /// <summary>
    /// 图片和对应的UI映射
    /// </summary>
    public int key ;
    /// <summary>
    /// 图片校验码,采用时间作为校验
    /// </summary>
    public string verifyCode;
    /// <summary>
    /// 图片要下载的地址
    /// </summary>
    public string url;
    /// <summary>
    ///( x,y)裁剪原点 (z,w)图片宽高
    /// </summary>
    public Vector4 imginfo ;
    /// <summary>
    /// 图片格式
    /// </summary>
    public TextureFormat textureFormat;
    /// <summary>
    /// 图片宽
    /// </summary>
    public int width;
    /// <summary>
    /// 图片高
    /// </summary>
    public int height;
}
public class IMGDownManager : MonoBehaviour {


    private static IMGDownManager _instance;
    public static IMGDownManager Instance
    {
        get {
            return _instance;
        }
    }
    private Queue<ImageEvent> threadEvents = new Queue<ImageEvent>();
    private int limitCoroutineCount=30;
    private int currentCoroutineCount=0;

    private void Awake()
    {
        _instance = this;
    }
    /// <summary>
    /// 添加事件
    /// </summary>
    public void AddEvent(ImageEvent imageEvent)
    {
        threadEvents.Enqueue(imageEvent);
    }
    public void OnUpdate()
    {
        if(threadEvents.Count > 0&&currentCoroutineCount<=limitCoroutineCount)
        {
            ImageEvent threadEvent = threadEvents.Dequeue();
            try
            {
                currentCoroutineCount+=1;
               StartCoroutine(OnDownLoad(threadEvent));
            }
            catch (System.Exception ex)
            {

            }
        }
    }
    IEnumerator OnDownLoad(ImageEvent imageEvent)
    {
        using (WWW www=new WWW(imageEvent.url))
        {

            yield return www;
            if (www.error!=null)
            {
                Debug.LogError("targetId:"+ imageEvent.key+ "图片地址:"+ imageEvent.url+"下载错误信息:"+ www.error);
                //如果下载失败,再放回队列里重新下载
                AddEvent(imageEvent);
                currentCoroutineCount -= 1;
            }
            else
            {
                currentCoroutineCount -= 1;
                Texture2D temp;
                if (imageEvent.imginfo != Vector4.zero)
                {

                    temp = ScaleTextureCutOut(www.texture, imageEvent.imginfo.z,
                   imageEvent.imginfo.w, (int)imageEvent.imginfo.x, (int)imageEvent.imginfo.y);
            }
                else
                {
                    if (imageEvent.width!=0&&imageEvent.height!=0)
                    {
                        temp = new Texture2D(imageEvent.width, imageEvent.height, imageEvent.textureFormat, false);
                    }                   
                    temp = www.texture;

            }    
               if (CenterAction.LoadCompleteImg!=null)
               {
                  //  Debug.Log("imageEvent key:"+imageEvent.key);
                    CenterAction.LoadCompleteImg(imageEvent.key,imageEvent.verifyCode,temp);
               }
                temp = null;
            }
        }         
    }

    /// <summary>
    /// 截图函数
    /// </summary>
    /// <param name="TUnit"></param>
    Texture2D ScaleTextureCutOut(Texture2D originalTexture, float originalWidth, float originalHeight, int distancex, int distancey)
    {
        Texture2D newTexture = new Texture2D(Mathf.CeilToInt(originalWidth), Mathf.CeilToInt(originalHeight));
        int maxX = originalTexture.width - 1;
        int maxY = originalTexture.height - 1;
        for (int y = 0; y < newTexture.height; y++)
        {
            for (int x = 0; x < newTexture.width; x++)
            {
                float targetX = x;
                float targetY = y;
                int x1 = Mathf.Min(maxX, Mathf.FloorToInt(targetX));
                int y1 = Mathf.Min(maxY, Mathf.FloorToInt(targetY));
                int x2 = Mathf.Min(maxX, x1 + 1);
                int y2 = Mathf.Min(maxY, y1 + 1);

                float u = targetX - x1;
                float v = targetY - y1;
                float w1 = (1 - u) * (1 - v);
                float w2 = u * (1 - v);
                float w3 = (1 - u) * v;
                float w4 = u * v;
                Color color1 = originalTexture.GetPixel(x1 + distancex, y1 + distancey);
                Color color2 = originalTexture.GetPixel(x2 + distancex, y1 + distancey);
                Color color3 = originalTexture.GetPixel(x1 + distancex, y2 + distancey);
                Color color4 = originalTexture.GetPixel(x2 + distancex, y2 + distancey);
                Color color = new Color(Mathf.Clamp01(color1.r * w1 + color2.r * w2 + color3.r * w3 + color4.r * w4),
                    Mathf.Clamp01(color1.g * w1 + color2.g * w2 + color3.g * w3 + color4.g * w4),
                    Mathf.Clamp01(color1.b * w1 + color2.b * w2 + color3.b * w3 + color4.b * w4),
                    Mathf.Clamp01(color1.a * w1 + color2.a * w2 + color3.a * w3 + color4.a * w4)
                );
                newTexture.SetPixel(x, y, color);
            }
        }
        newTexture.anisoLevel = 2;
        newTexture.Apply();
        Destroy(originalTexture);
        return newTexture;
    }
    private void Update()
    {
        OnUpdate();
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tianyongheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值