unity3d 示例化从assetbundle加载的游戏对象丢失动画剪辑

nlejzf6q  于 2023-02-05  发布在  其他
关注(0)|答案(1)|浏览(206)

我把我所有的npc的预置打包到assetbundle中,包含所有的依赖项,但是当我加载完一个npc的所有依赖项并将其示例化到场景中时,有时它上面的动画剪辑无法播放。我打印animator。GetCurrentAnimatorClipInfo(0).长度我发现它是0.所以看起来我已经失去了这个动画师的所有动画剪辑.有趣的是,它并没有发生在所有的npc,我找不出他们之间有什么不同。
我使用以下代码将assetbundle名称附加到所有资产。

private void SelectionAndAssetsListChange()
{
    EditorUtility.ClearProgressBar();
    selection = Selection.objects;
    //assets = new AssetImporter[selection.Length];
    if (selection.Length > 0)
    {
        for (int i = 0; i < selection.Length; i++)
        {
            string assetPath = AssetDatabase.GetAssetPath(selection[i]);                
           
            string[] dps = AssetDatabase.GetDependencies(assetPath);
            int length = dps.Length;                 
            int index = 0;
            foreach (var dp in dps)
            {
                if (EditorUtility.DisplayCancelableProgressBar("Changing Assets's ab name ", "Changing No." + index + "/" + length, (float)index / length))
                {
                    EditorUtility.ClearProgressBar();
                    return;
                }

                if (dp.EndsWith(".cs"))
                    continue;
                AssetImporter dpAsset = AssetImporter.GetAtPath(dp);                    
                string assetNameDPs = dp.Substring("Assets".Length + 1);                                        
                assetNameDPs = assetNameDPs.Replace(Path.GetExtension(assetNameDPs), ".data");
                assetNameDPs = Path.Combine("assetbundle", assetNameDPs);
                assetNameDPs = assetNameDPs.Replace("\\", "/");
                dpAsset.assetBundleName = assetNameDPs;
                index++;
            }
            EditorUtility.ClearProgressBar();
        }
    }
}

以下代码用于加载资产捆绑包,我使用了2个字典TempABGO_Dict和TempDPSAB_Dict,以确保不会双重加载。
x一个一个一个一个x一个一个二个x
这是我用来构建BuildAssetBundles的。

BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, compressMode, EditorUserBuildSettings.activeBuildTarget);
izj3ouym

izj3ouym1#

首先是一个一般性的说明,您可以使用
yield返回null;
你也可以减少很多,比如说之前和之后

AssetBundleCreateRequest ab = AssetBundle.LoadFromFileAsync(path);

for环路内等等。
然后在SingleDpsABLoad中,您不必等待

ab = AssetBundle.LoadFromFileAsync(....);

才能真正完成!你只要继续

dc.finihed = true

所以你可能很幸运,有时候剩下的多余的

yield return 0;

for循环中的etc只需要足够的延迟来及时加载它^^
所以你可能更愿意做一些

IEnumerator SingleDpsABLoad(DpsContainer dpsContainer)
{
    var path = Path.Combine(Application.streamingAssetsPath, dpsContainer.abName);

    if (!File.Exists(path))
    {
        Debug.LogError("Can't find path:" + path);
        yield break;
    }

    var ab = AssetBundle.LoadFromFileAsync(path);  

    // actually wait until the async operation is done
    yield return ab;

    // can also make that one async
    yield return ab.assetBundle.LoadAllAssetsAsync();

    dpsContainer.AB = ab.assetBundle;
    dpsContainer.finishLoad = true;
}

IEnumerator SingleTempGOABLoad(string abName)
{
    Debug.Log(" 1 SingleTempGOABLoad :" + abName);

    // personally I would start with that check here already
    var path = Path.Combine(Application.streamingAssetsPath, abName);

    if (!File.Exists(path))
    {
        Debug.Log("Can't find path:" + path);
        yield break;
    }
    
    if (TempABGO_Dict.ContainsKey(abName)) yield break;

    var allDps = mainManifest.GetAllDependencies(abName);
         
    foreach (var dps in allDps)
    {
        if (TempDPSAB_Dict.TryGetValue(dps, out var dpsContainer))
        {
            dpsContainer.refCount++;
        }
        else
        {
            dpsContainer = new DpsContainer(null, dps);
            
            TempDPSAB_Dict[dps] = dpsContainer;
            StartCoroutine(SingleDpsABLoad(dps));
        }
    }
    
    // using System.Linq
    yield return new WaitUntil(() => TempDPSAB_Dict.All(kvp => kvp.Value.finishLoad));
   

    var ab = AssetBundle.LoadFromFileAsync(path);
    yield return ab;

    var abReq = ab.assetBundle.LoadAllAssetsAsync<GameObject>();
    yield return abReq;

    var go = (GameObject)abReq.asset;
   
    TempABGO_Dict[abName] = new TempPrefabABPair(ab.assetBundle, go, allDps));
}

相关问题