本文主要是介绍Unity Alembic 在打包后报错:failed to load alembic at C://***.abc,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
ABC动画打Windows包后,加载时报错?找不到.abc文件。
你可能在用Unity做Windows 平台的项目时,遇到过使用Alembic动画的需求。
在资源管理方面,如果你的工作流是:所有ABC动画制作成预制,并且在项目打包时,将他们放在场景中,并提前将Active勾选掉,隐藏起来,在需要用的时候再显示出来,播放动画。那么你将不会遇到上述问题。
因此,如果你只是为了着急解决问题,对你而言,可以用上述方式来解决你的报错问题。
然而,作为一名资深游戏开发人员,真的很难忍受这种资源管理方式,即便现在不做游戏了,依然希望我的资源是在用到的时候再加载。不用的时候,他就应该呆在它的小窝里好好待着,而不是跑到场景里猫起来= = 况且也不能满足资源热更新的需求。
因此,经过一些国内外网站上对于该问题的搜索及自身的思考,了解了问题产生的原因,也总结了一套方案。
原因:
由于abc文件是一种特殊的数据格式,数据量是巨大的,用他们讲的我没看懂的英文说,是multigig bloat,类似巨量数据膨胀的意思,英文并不如编程优秀= = ,因此,它的加载方式也比较复杂并不像animationClip那般简单。为何官方没有提供一个动态为其Stream的接口呢?从19年的一个Unity官方程序员的留言中看到,当时应该是还没写,大概至今已经忘了支持了吧。。
解决方案:
不过,你可以在打包时,注册构建后处理回调。在回调中,将项目用到的abc文件拷贝,并复制到打包后的目标文件夹下的streamingAssets目录里。这样对于客户端开发人员来说,就可以无感于abc繁琐的操作,亦可优雅的使用既有框架对资源进行加载和卸载。项目中的streamingassets文件夹中也没有任何变化。
但其实资源大小并未真正减少。只是为了满足动态加载时内心的完美体验。哈哈,那么Talk完了,ShowCode.(注意: 使用時請將它放到Editor文件夾下。)
/* 工具由來:* 若項目ABC動畫,並未在Build時放入場景,通過SetActive去打開。* 而是,通過Resources、Addressable或第三方解決方案等AB包的* 方式加載的話,則會出現ABC文件無法找到的報錯。** 這是由於ABC工作流機制所致。但Alembic並未暴露可改引用路徑的接口。* * 因此,我們需要將ABC文件Copy到打包目錄中,從而使得在程序運行時,* 動態加載的動畫文件,可以Stream到其引用的ABC。* 該工具就是為了做這個工作而寫。** 使用:時請將它放到Editor文件夾下。* * CopyRight@ Vimala Eric* 2023.12.3*/using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;namespace Editor
{/// <summary>/// ABC文件打包後處理工具/// </summary>class AbcBuildPostProcess:IPreprocessBuildWithReport{/// <summary>/// Abc文件根目錄/// </summary>const string AbcFolder = "/Alembic";/*你可以填空,默認掃描全局abc文件。我的建議起碼填所有abc資源的根目錄,減少打包時的準備時間*/const string KUnsupportedTarget = "Alembic only supports the following build targets: Windows 64-bit, macOS X, and Linux 64-bit.";static readonly HashSet<KeyValuePair<string, string>> FilesToCopy = new ();public int callbackOrder { get; }public void OnPreprocessBuild(BuildReport report){var target = report.summary.platform;if (!TargetIsSupported(target)){Debug.LogException(new Exception(KUnsupportedTarget));return;}//初始化 filesToCopyInitFilesToCopy(report.summary);Copy();}static void Copy(){StringBuilder sb = new StringBuilder();foreach (var files in FilesToCopy){if (!File.Exists(files.Key)){continue;}var dir = Path.GetDirectoryName(files.Value);if (dir != null && !Directory.Exists(dir)){Directory.CreateDirectory(dir);}if (File.Exists(files.Value)){var attrs = File.GetAttributes(files.Value);attrs &= ~FileAttributes.ReadOnly;File.SetAttributes(files.Value, attrs);}File.Copy(files.Key, files.Value, true);sb.Append(Path.GetFileName(files.Key)+",");}Debug.Log($"PostProcess Copy ABC:{sb}");FilesToCopy.Clear();}static void InitFilesToCopy(BuildSummary summary){var streamingAssetsPath = GetOutPutStreamingAssetsPath(summary);//get all abc filesvar abcFiles = Directory.GetFiles(Application.dataPath+AbcFolder,"*.abc");int assetsIndex = 0;foreach (var abcFile in abcFiles){assetsIndex = abcFile.IndexOf("/Assets", StringComparison.Ordinal);var localPath = abcFile.Substring(assetsIndex, abcFile.Length - assetsIndex);FilesToCopy.Add(new KeyValuePair<string, string>(abcFile, $"{streamingAssetsPath}{localPath}"));}}static string GetOutPutStreamingAssetsPath(BuildSummary summary){switch (summary.platform){case BuildTarget.StandaloneOSX:return Path.Combine(summary.outputPath, "Contents/Resources/Data/StreamingAssets");case BuildTarget.StandaloneLinux64:case BuildTarget.StandaloneWindows64:var name = Path.ChangeExtension(summary.outputPath, null);return name + "_Data/StreamingAssets";default:throw new NotImplementedException();}}static bool TargetIsSupported(BuildTarget target){return target == BuildTarget.StandaloneOSX || target == BuildTarget.StandaloneWindows64 || target == BuildTarget.StandaloneLinux64;}}
}
白羽小镇
VimalaEric
2023.12.3记
这篇关于Unity Alembic 在打包后报错:failed to load alembic at C://***.abc的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!