需要載入大量圖片到Image並顯示,基本方法有2種,用WWW或者c#的FileStream。考慮到協程,異步,以及把代碼統一寫或者分開寫,衍生出5、6種方法。
job system只能處理值類型,幫不上忙。ecs也主要集中在處理update裏面的內容,似乎也不使用。還考慮過多線程,這裏不是很確定。unity多線程過程中,子線程不能使用unity的api,就只能用c#把文件讀取過程加速,對多線程不熟,就放棄了。
結論
會出現3種效果,在使用FileStream異步,在統一的地方寫代碼適應畢竟廣。
測試方法,加載102張512*512分辨率的圖片,顯示成一個圖片下拉列表,樣子如下
方法一、統一調用WWW協程
GuiController.CS
//方法一、統一調用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佔用信息
方法二、統一調用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佔用信息