最近做项目处理实时接收数据,每条数据对应一张图片,为了提高性能,
先显示每条数据对应生成模型,然后将图片做好与模型的映射,然后再加上图片校验码和模型之间的校验码作比较
等待图片下载完毕后,会将图片准确无误的给对应的模型。
首先思路是
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&¤tCoroutineCount<=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();
}
}