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

标签 c# unity-game-engine unity-webgl assetbundle

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

  1. 我已划分为 1000 x 1000 m (1km) 的图 block

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

  3. 加载\卸载这些资源包,我正在计算我的播放器/相机与图 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 。

性能问题:

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

  1. 其性能不佳(循环预计会增长)。

  2. Webgl 有时很长,并且运行不流畅或不流畅。

  3. 下载内容(资源包)时,尽管使用了 LoadAssetAsync,游戏还是卡住了

有人可以帮我编写更高效、更优雅的方式来加载/卸载资源包吗?

最佳答案

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

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

相关文章:

android - 在 Unity3D 中构建后如何使 IBM Watson VR Speech Sandbox 在 Android 上运行

unity-game-engine - 力场着色器展开纹理不起作用

unity3d - 修改 Unity WebGL 构建 URL

unity-game-engine - 确保 polymer 构建过程不会干扰我的元素的依赖性

c# - 在不接受新值的情况下搜索 ComboBox

c# - 用于转到源代码管理资源管理器中特定项目的 Visual Studio 命令

c# - Java 与 .Net 中的对象生命周期

c# - 403 禁止 Unity3D C#

c# - 从 sendMessage 返回值或在 unity webgl 中交替

c# - 使用 AT 命令通过 GSM 发送多部分短信