Unity iOS 卸载 assetbundle 场景时崩溃

Unity iOS crash when unloading assetbundle scene

我在另一个项目中分离了一些小游戏,将它们全部加载到一个项目中。我已经使用 Unity 2018.4.9 版本成功创建了资产包并将它们放入 StreamingAssets 文件夹中。 Unity Editor 加载和卸载场景成功,但是当我构建 IOS 时,加载场景成功,没问题,但是当我想卸载它时,它给我这样的内存错误:

我认为当系统试图删除与资产包相关的游戏对象时会发生此错误。因为当我想在卸载场景之前删除场景中的所有游戏对象时,它会给出同样的错误。此错误仅发生在 iOS 中,而不是编辑器中。 Unity Editor 成功卸载资产包场景。这是我 load/unload 资产包及其场景的代码:

当我 运行 UnloadAdditiveScene()

时发生错误
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class MarketplaceBundleGameLoader : MonoBehaviour
{
    AssetBundle myLoadAssetBundle;
    AssetBundle[] assetBundles;
    float progress = 0f;
    List<GameObject> objectsToBeDisabled;

    public bool passingToAnotherScene = false;
    public static string bundlePath;
    public static MarketplaceBundleGameLoader Instance;
    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            objectsToBeDisabled = new List<GameObject>();
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            DestroyImmediate(gameObject);
        }
    }

    public void AddObjectToBeDisabled(GameObject go)
    {
        objectsToBeDisabled.Add(go);
    }

    public void LoadMultipleBundles(params string[] pathes)
    {
        if (passingToAnotherScene)
        {
            return;
        }
        passingToAnotherScene = true;
        StartCoroutine(LoadMultipleBundlesTask(pathes));
    }

    IEnumerator LoadMultipleBundlesTask(params string[] pathes)
    {
        progress = 0;
        assetBundles = new AssetBundle[pathes.Length];
        Resources.UnloadUnusedAssets();
        yield return FaderManager.Instance.CloseTheatre();
        for (int i = 0; i < objectsToBeDisabled.Count; i++)
        {
            objectsToBeDisabled[i].SetActive(false);
        }
        SceneManager.LoadScene("BundleGameLoader", LoadSceneMode.Additive);
        yield return FaderManager.Instance.OpenTheatre();
        for (int i = 0; i < pathes.Length; i++)
        {
            AssetBundleCreateRequest abcr = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(Path.Combine(StaticVariables.GetStreamingPath(), pathes[i])));
            while (abcr.progress < 0.9f)
            {
                progress = (i / (1f + pathes.Length)) + abcr.progress / (1f + pathes.Length);
                yield return new WaitForFixedUpdate();
            }
            assetBundles[i] = abcr.assetBundle;
        }
        string[] scenePath = assetBundles[0].GetAllScenePaths();
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(System.IO.Path.GetFileNameWithoutExtension(scenePath[0]), LoadSceneMode.Additive);
        asyncLoad.allowSceneActivation = false;
        float totalTimer = 0f;
        while (asyncLoad.progress < 0.9f)
        {

            totalTimer += Time.deltaTime;
            progress = ((float)pathes.Length / (pathes.Length + 1)) + asyncLoad.progress / (pathes.Length + 1);
            yield return null;
        }
        progress = 1.05f;
        float waitDifferenceTime = Mathf.Max(0.1f, 3f - totalTimer);
        yield return new WaitForSeconds(waitDifferenceTime);
        Resources.UnloadUnusedAssets();
        yield return FaderManager.Instance.CloseTheatre();
        asyncLoad.allowSceneActivation = true;

        AsyncOperation asyncUnload = SceneManager.UnloadSceneAsync(SceneManager.GetSceneByName("BundleGameLoader"));
        while (asyncUnload.progress < 0.9f)
        {
            yield return null;
        }
        passingToAnotherScene = false;
        yield return FaderManager.Instance.OpenTheatre();
    }


    public float GetProgress()
    {
        return progress;
    }

    public void UnloadAdditiveScene(string unloadName)
    {
        StartCoroutine(UnloadAdditiveSceneSceneTask(unloadName));
    }

    IEnumerator UnloadAdditiveSceneSceneTask(string unloadName)
    {
        yield return FaderManager.Instance.CloseTheatre();
        for (int i = 0; i < assetBundles.Length; i++)
        {
            assetBundles[i].Unload(false);
        }
        yield return new WaitForEndOfFrame();
        AsyncOperation asyncUnload = SceneManager.UnloadSceneAsync(unloadName);
        while(!asyncUnload.isDone)
        {
            yield return new WaitForEndOfFrame();
        }
        yield return new WaitForEndOfFrame();
        SceneManager.SetActiveScene(SceneManager.GetSceneAt(0));
        //AssetBundle.UnloadAllAssetBundles(true);
        // AssetBundle[] bundles = Resources.FindObjectsOfTypeAll<AssetBundle>();
        // //Debug.Log(bundles.Length);
        // for (int i = 1; i < bundles.Length; i++)
        // {
        //     bundles[i].Unload(true);
        // }
        //Resources.UnloadUnusedAssets();
        for (int i = 0; i < objectsToBeDisabled.Count; i++)
        {
            objectsToBeDisabled[i].SetActive(true);
        }
        objectsToBeDisabled.Clear();

        yield return FaderManager.Instance.OpenTheatre();
    }

    // public void loadScene(string sceneName)
    // {
    //  if(passingToAnotherScene)
    //  {
    //      return;
    //  }
    //  passingToAnotherScene = true;
    //  StartCoroutine(loadSceneTask(sceneName));
    // }

    // public IEnumerator loadSceneTask(string sceneName)
    // {
    //  yield return FaderController.Instance.fadeScreen(0.5f);
    //     yield return new WaitForSeconds(0.5f);

    //  SceneManager.LoadScene("SeasonsLoading");

    //  yield return FaderController.Instance.unfadeScreen(0.5f);
    //  AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
    //     asyncLoad.allowSceneActivation = false;
    //     float totalTimer = 0f;
    //     while(asyncLoad.progress < 0.9f)
    //     {
    //         totalTimer += Time.deltaTime;
    //         yield return null;
    //     }
    //     float waitDifferenceTime = Mathf.Max(0.1f, 3f - totalTimer);
    //     yield return new WaitForSeconds(waitDifferenceTime);
    //  yield return FaderController.Instance.fadeScreen(0.5f);
    //  asyncLoad.allowSceneActivation = true;
    //  passingToAnotherScene = false;
    //  yield return FaderController.Instance.unfadeScreen(0.5f);

    //     //yield return new WaitForSeconds(0.5f);


    // }

    public void RestartScene(string sceneName)
    {
        if (passingToAnotherScene)
        {
            return;
        }
        passingToAnotherScene = true;
        StartCoroutine(RestartSceneTask(sceneName));
    }

    public IEnumerator RestartSceneTask(string sceneName)
    {
        yield return FaderManager.Instance.CloseTheatre();
        AsyncOperation asyncUnload = SceneManager.UnloadSceneAsync(SceneManager.GetSceneByName(sceneName));
        while (asyncUnload.progress < 0.9f)
        {
            yield return null;
        }
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
        while (asyncLoad.progress < 0.9f)
        {
            yield return null;
        }
        passingToAnotherScene = false;
        yield return FaderManager.Instance.OpenTheatre();
    }


    public void ChangeScene(string unloadScene, string loadScene)
    {
        if (passingToAnotherScene)
        {
            return;
        }
        passingToAnotherScene = true;
        StartCoroutine(ChangeSceneTask(unloadScene, loadScene));
    }

    public IEnumerator ChangeSceneTask(string unloadScene, string loadScene)
    {
        yield return FaderManager.Instance.CloseTheatre();
        AsyncOperation asyncUnload = SceneManager.UnloadSceneAsync(SceneManager.GetSceneByName(unloadScene));
        while (asyncUnload.progress < 0.9f)
        {
            yield return null;
        }
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(loadScene, LoadSceneMode.Additive);
        while (asyncLoad.progress < 0.9f)
        {
            yield return null;
        }
        passingToAnotherScene = false;
        yield return FaderManager.Instance.OpenTheatre();
    }
}

禁用播放器设置中的 "Strip Engine Code" 选项解决了我的问题。在 2018.3.4 中,当您禁用此选项时,Xcode 给出链接器错误。但在2019.2.6f,它起作用了。