1. 程式人生 > >Unity 非同步載入圖片

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(); } }