我有一个非常大型 3D 世界/环境,其中
我已划分为 1000 x 1000 m (1km) 的图 block 。
制作了所有图 block 的资源包,目前只有 5 个资源包(预计会大幅增长,可能在 1000 个左右) Assets 包)。
- 加载\卸载这些资源包,我正在计算我的播放器/相机与图 block 的距离,然后调用 加载或卸载。
请参阅下面的简单脚本(根据距离加载图 block ):
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;
}
以及用于销毁(实际上停用对象,因为销毁是昂贵的功能) bundle 。
性能问题:
代码工作正常,我能够加载/卸载资源包,但问题是
其性能不佳(循环预计会增长)。
Webgl 有时很长,并且运行不流畅或不流畅。
- 下载内容(资源包)时,尽管使用了 LoadAssetAsync,游戏还是卡住了。
有人可以帮我编写更高效、更优雅的方式来加载/卸载资源包吗?
最佳答案
您应该首先查看分析器并查看应用程序的瓶颈,如果它卡在加载包(协程仍在主线程上运行并可能导致滞后),您可能需要使用 async loading 。但是你会想提前调用它们(当玩家靠近另一个 block 时,所以当他实际到达该 block 时它就准备好了)。 如果您的瓶颈位于其他地方,例如与渲染有关的问题,您可能会以其他方式处理它(具有较少顶点/三角形的较小 Assets 或更积极的剔除)。无论哪种方式,为了更好地判断,您都需要定位问题所在,但从第一眼看来,似乎是在主线程上加载资源才是问题所在。
关于c# - 使用资源包在 unity webgl 中加载/卸载巨大的世界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55570170/