使用资产包在团结webgl中加载/卸载巨大的世界

问题描述 投票:2回答:1

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

  1. 我分为1000 x 1000米(1公里)的瓷砖。
  2. 制作所有瓷砖的资产捆绑,目前只有5个资产捆绑(预计可能大幅增长约1000个资产捆绑)。
  3. 正在加载\卸载这些资产包,我正在计算我的播放器/相机与磁贴的距离,然后调用加载或卸载。

请参阅下面的简单脚本(根据距离加载图块):

        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则对已加载包的游戏对象(如果可用)执行deactive。以下是用于下载资产包的代码段:

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;
}

并且为了销毁(实际上停用对象,因为破坏是昂贵的功能)捆绑。

绩效问题:

代码工作正常,我能够加载/卸载资产包但问题是

  1. 它的性能不好(预计循环会增长)。
  2. Webgl有时很长,它不是无缝或平滑运行。
  3. 下载内容(资产包)时,尽管使用了LoadAssetAsync,游戏也会冻结。

任何人都可以帮我写更高效,更优雅的方式来加载/卸载资产包吗?

c# unity3d unity-webgl assetbundle
1个回答
2
投票

您首先应该查看分析器并查看应用程序的阻塞点,如果它在加载捆绑包时停留(协同程序仍在主线程上运行并且可能导致滞后)您可能想要使用async loading。但是你想要提前打电话给那些(当玩家接近另一个大块时,所以当他实际到达大块时就准备好了)。如果您的瓶颈位于其他地方,例如与渲染有关的事情,您可能会以其他方式接近它(较小的资产具有较少的顶点/三角形或更积极的剔除)。无论哪种方式更好的判断你需要找到问题的位置,但从第一眼看,似乎在主线程上加载资产是问题。

© www.soinside.com 2019 - 2024. All rights reserved.