写在前面
最近项目需要在Unity中完成一个非常耗时的工作,所以学习了下异步加载的流程,这里做了一个demo,异步加载AB包,其实异步加载场景等,原理差不多。
效果
关键讲解
主要就是在协程里使用AssetBundle.LoadFromFileAsync()
异步加载AB包,
AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(abPath);
其返回的AssetBundleCreateRequest abcr
有一个progress
属性能够查看AB包加载进度,isDone
属性能查看AB包是否加载完成,我们这里用Lerp
平滑过度一下。这里之所以用slider.value<=0.99
做条件而不用isDone
是因为项目太小,一瞬间就加载完了。如果是大项目就用isDone
while (slider.value<=0.99) {
//平滑过度
slider.value = Mathf.Lerp(slider.value, abcr.progress, Time.deltaTime);
text.text = (int)(slider.value * 100) + "%";
yield return null;
最后加载图片即可,其实这里也可以用异步加载Asset,但是加载图片不耗时,我就用同步了。
Image[] images = display.GetComponentsInChildren<Image>();
for (int i = 0; i < images.Length; i++) {
images[i].sprite = abcr.assetBundle.LoadAsset<Sprite>(abcr.assetBundle.GetAllAssetNames()[i]);
}
最后的最后卸载AB包,false
是为了不写在场景中还在使用的AB包。Resources.UnloadUnusedAssets();
是为了清理不用的资源。
abcr.assetBundle.Unload(false);
Resources.UnloadUnusedAssets();
完整代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoadManager : MonoBehaviour {
public GameObject loadPlane;
public Slider slider;
public Text text;
public GameObject display;
public void LoadImage() {
StartCoroutine(Loading());
}
IEnumerator Loading() {
loadPlane.SetActive(true);
string abPath = Application.dataPath;
abPath = abPath.Substring(0, abPath.Length - 6) + "ab"+"/image";
AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(abPath);
while (slider.value<=0.99) {
//平滑过度
slider.value = Mathf.Lerp(slider.value, abcr.progress, Time.deltaTime);
text.text = (int)(slider.value * 100) + "%";
yield return null;
}
Image[] images = display.GetComponentsInChildren<Image>();
for (int i = 0; i < images.Length; i++) {
images[i].sprite = abcr.assetBundle.LoadAsset<Sprite>(abcr.assetBundle.GetAllAssetNames()[i]);
}
loadPlane.SetActive(false);
abcr.assetBundle.Unload(false);
Resources.UnloadUnusedAssets();
}
}
项目地址
https://github.com/hahahappyboy/UnityProjects/tree/main/ABSyncLoad
写在后面
什么时候复刻可莉啊!!!