У меня очень большой трехмерный мир / Окружающая среда который
У меня есть , разделенные на 1000 x 1000 м (1 км) плиток .
Созданы пакеты активов из всех плиток , и в настоящее время существует только 5 пакетов активов (ожидается значительный рост, возможно, около 1000
пакеты активов).
- Загрузка \ выгрузка этих пакетов активов , я рассчитываю расстояние моего игрока / камеры с плиткой и затем призываю к
загрузить или разгрузить.
Пожалуйста, смотрите ниже простой скрипт (Загрузка плиток на основе расстояния):
public Vector3 tileSize;
public int maxDistance;
public MultipleAssetBundleLoader[] tiles;
void Start()
{
this.tiles = FindObjectsOfType<MultipleAssetBundleLoader>();
}
void DeactivateDistantTiles()
{
foreach (MultipleAssetBundleLoader tile in tiles)
{
Vector3 tilePosition = tile.gameObject.transform.position + (tileSize / 2f);
float xDistance = Mathf.Abs(tilePosition.x - playerPosition.x);
float zDistance = Mathf.Abs(tilePosition.z - playerPosition.z);
if (xDistance + zDistance > maxDistance)
{
tile.DestroyBundleObject();
//tile.SetActive(false);
}
else
{
tile.StartDownloadingAB();
}
}
}
void Update()
{
DeactivateDistantTiles();
}
Функция StartDownloadingAB просто загружает пакеты ресурсов и создает экземпляр игрового объекта с сервера или из кэша, в то время как DestroyBundleObject отключает игровой объект загруженного пакета (если доступно).
Вот фрагмент кода для загрузки пакета ресурсов:
public void StartDownloadingAB()
{
if (BundleLoadStatus == BundleLoadStatusEnum.bundleNotLoadedYet)
{
BundleLoadStatus = BundleLoadStatusEnum.bundlesLoading;
downloadABRef = StartCoroutine(DownloadAB());
}
else if (bundleObjectsDeactivated == true && BundleLoadStatus == BundleLoadStatusEnum.bundlesHasLoaded)
{
BundleObjectActive(true);
}
}
public IEnumerator DownloadAB()
{
if (isBundleLoading == true)
yield return false;
BundleLoadStatus = BundleLoadStatusEnum.bundlesLoading;
isBundleLoading = true;
//Debug.Log("loading " + url);
www = UnityWebRequestAssetBundle.GetAssetBundle(url);
yield return www.SendWebRequest();
if (www.error != null)
{
Debug.LogError("assetBundleURL : " + url);
Debug.LogError("www error : " + www.error);
www.Dispose();
www = null;
yield break;
}
AssetBundle bundle = ((DownloadHandlerAssetBundle)www.downloadHandler).assetBundle;
GameObject bundlePrefab = null;
bundlePrefab = (GameObject)bundle.LoadAsset(bundle.name);
AssetBundleRequest bundlePrefabAsync = bundle.LoadAssetAsync(bundle.name, typeof(GameObject));
yield return bundlePrefab;
if (bundlePrefab != null)
{
//assetBundleToLoadObj = (GameObject)Instantiate(bundlePrefab);
assetBundleToLoadObj = Instantiate(bundlePrefabAsync.asset as GameObject);
assetBundleToLoadObj.transform.parent = envParent.transform;
floorL7MeshRenderer.enabled = false;
}
www.Dispose();
www = null;
// try to cleanup memory
Resources.UnloadUnusedAssets();
bundle.Unload(false);
//bundle = null;
isBundleLoading = false;
BundleLoadStatus = BundleLoadStatusEnum.bundlesHasLoaded;
}
И для уничтожения (на самом деле деактивация объекта, так как уничтожение является дорогой функцией) связки.
Проблема производительности:
Код работает нормально, и я могу загрузить / выгрузить пакет ресурсов, но проблемы
его производительность не очень хорошая (ожидается рост цикла).
Иногда Webgl длинноногий, он не гладкий или плавный.
- При загрузке контента (комплектов ресурсов) игра останавливается, несмотря на использование LoadAssetAsync .
Может кто-нибудь помочь мне написать более эффективный и элегантный способ загрузки / выгрузки пакета активов?