gpt4 book ai didi

c# - 使用 Assets 包在 unity webgl 中加载/卸载巨大的世界

转载 作者:行者123 更新时间:2023-11-30 22:55:07 25 4
gpt4 key购买 nike

我有一个非常大型 3D 世界/环境

  1. 分成了 1000 x 1000 米(1 公里)的方 block

  2. 制作了所有图 block 的 Assets 包,目前只有 5 个 Assets 包(预计会显着增长,可能在 1000 左右 Assets 包)。

  3. 加载\卸载这些 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 函数只是从服务器或缓存中下载 Assets 包并实例化游戏对象,而 DestroyBundleObject 则停用加载包的游戏对象(如果可用)。以下是下载 Assets 包的代码片段:

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 。

性能问题:

代码工作正常,我可以加载/卸载 Assets 包但问题是

  1. 它的性能不好(预计循环会增长)。

  2. Webgl 有时会很长,而且它不是无缝或流畅运行的。

  3. 尽管使用了 LoadAssetAsync,但在下载内容( Assets 包)时游戏会卡住

谁能帮我写出更高效、更优雅的方式来加载/卸载 Assets 包?

最佳答案

您应该首先查看分析器并查看您的应用程序的阻塞点,如果它卡在加载包(协程仍在主线程上运行并可能导致延迟),您可能需要使用 async loading .但是你会想提前调用那些(当玩家靠近另一个 block 时,所以当他真正到达 block 时它就准备好了)。如果您的瓶颈在其他地方,例如与渲染有关的事情,您可能会以其他方式处理它(具有较少顶点/三角形的较小 Assets 或更积极的剔除)。无论哪种方式,为了更好地判断,您都需要找到问题所在,但乍一看,似乎是在主线程上加载 Assets 才是问题所在。

关于c# - 使用 Assets 包在 unity webgl 中加载/卸载巨大的世界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55570170/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com