using System.IO; using UnityEngine; using YooAsset; namespace AlicizaX.Resource.Runtime { internal partial class ResourceManager { /// /// 远端资源地址查询服务类 /// private class RemoteServices : IRemoteServices { private readonly string _defaultHostServer; private readonly string _fallbackHostServer; public RemoteServices(string defaultHostServer, string fallbackHostServer) { _defaultHostServer = defaultHostServer; _fallbackHostServer = fallbackHostServer; } string IRemoteServices.GetRemoteMainURL(string fileName) { return $"{_defaultHostServer}/{fileName}"; } string IRemoteServices.GetRemoteFallbackURL(string fileName) { return $"{_fallbackHostServer}/{fileName}"; } } /// /// 资源文件流加载解密类 /// private class FileStreamDecryption : IDecryptionServices { /// /// 同步方式获取解密的资源包对象 /// 注意:加载流对象在资源包对象释放的时候会自动释放 /// AssetBundle IDecryptionServices.LoadAssetBundle(DecryptFileInfo fileInfo, out Stream managedStream) { BundleStream bundleStream = new BundleStream(fileInfo.FileLoadPath, FileMode.Open, FileAccess.Read, FileShare.Read); managedStream = bundleStream; return AssetBundle.LoadFromStream(bundleStream, fileInfo.FileLoadCRC, GetManagedReadBufferSize()); } /// /// 异步方式获取解密的资源包对象 /// 注意:加载流对象在资源包对象释放的时候会自动释放 /// AssetBundleCreateRequest IDecryptionServices.LoadAssetBundleAsync(DecryptFileInfo fileInfo, out Stream managedStream) { BundleStream bundleStream = new BundleStream(fileInfo.FileLoadPath, FileMode.Open, FileAccess.Read, FileShare.Read); managedStream = bundleStream; return AssetBundle.LoadFromStreamAsync(bundleStream, fileInfo.FileLoadCRC, GetManagedReadBufferSize()); } public byte[] ReadFileData(DecryptFileInfo fileInfo) { throw new System.NotImplementedException(); } public string ReadFileText(DecryptFileInfo fileInfo) { throw new System.NotImplementedException(); } private static uint GetManagedReadBufferSize() { return 1024; } } /// /// 资源文件偏移加载解密类 /// private class FileOffsetDecryption : IDecryptionServices { /// /// 同步方式获取解密的资源包对象 /// 注意:加载流对象在资源包对象释放的时候会自动释放 /// AssetBundle IDecryptionServices.LoadAssetBundle(DecryptFileInfo fileInfo, out Stream managedStream) { managedStream = null; return AssetBundle.LoadFromFile(fileInfo.FileLoadPath, fileInfo.FileLoadCRC, GetFileOffset()); } /// /// 异步方式获取解密的资源包对象 /// 注意:加载流对象在资源包对象释放的时候会自动释放 /// AssetBundleCreateRequest IDecryptionServices.LoadAssetBundleAsync(DecryptFileInfo fileInfo, out Stream managedStream) { managedStream = null; return AssetBundle.LoadFromFileAsync(fileInfo.FileLoadPath, fileInfo.FileLoadCRC, GetFileOffset()); } public byte[] ReadFileData(DecryptFileInfo fileInfo) { throw new System.NotImplementedException(); } public string ReadFileText(DecryptFileInfo fileInfo) { throw new System.NotImplementedException(); } private static ulong GetFileOffset() { return 32; } } /// /// 资源文件解密流 /// public class BundleStream : FileStream { public const byte KEY = 64; public BundleStream(string path, FileMode mode, FileAccess access, FileShare share) : base(path, mode, access, share) { } public BundleStream(string path, FileMode mode) : base(path, mode) { } public override int Read(byte[] array, int offset, int count) { var index = base.Read(array, offset, count); for (int i = 0; i < array.Length; i++) { array[i] ^= KEY; } return index; } } public class StreamingAssetsDefine { /// /// 根目录名称(保持和YooAssets资源系统一致) /// public const string RootFolderName = "package"; } #if UNITY_EDITOR internal class PreprocessBuild : UnityEditor.Build.IPreprocessBuildWithReport { public int callbackOrder { get { return 0; } } /// /// 在构建应用程序前处理 /// 原理:在构建APP之前,搜索StreamingAssets目录下的所有资源文件,然后将这些文件信息写入内置清单,内置清单存储在Resources文件夹下。 /// public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report) { string saveFilePath = "Assets/AATemp/Resources/BuildinFileManifest.asset"; if (File.Exists(saveFilePath)) { File.Delete(saveFilePath); UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); } string folderPath = $"{Application.dataPath}/StreamingAssets/{StreamingAssetsDefine.RootFolderName}"; DirectoryInfo root = new DirectoryInfo(folderPath); if (root.Exists == false) { Debug.LogWarning($"没有发现YooAsset内置目录 : {folderPath}"); return; } var manifest = ScriptableObject.CreateInstance(); FileInfo[] files = root.GetFiles("*", SearchOption.AllDirectories); foreach (var fileInfo in files) { if (fileInfo.Extension == ".meta") continue; if (fileInfo.Name.StartsWith("PackageManifest_")) continue; BuildinFileManifest.Element element = new BuildinFileManifest.Element(); element.PackageName = fileInfo.Directory.Name; element.FileCRC32 = YooAsset.HashUtility.FileCRC32(fileInfo.FullName); element.FileName = fileInfo.Name; manifest.BuildinFiles.Add(element); } if (Directory.Exists("Assets/AATemp/Resources") == false) Directory.CreateDirectory("Assets/AATemp/Resources"); UnityEditor.AssetDatabase.CreateAsset(manifest, saveFilePath); UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); Debug.Log($"一共{manifest.BuildinFiles.Count}个内置文件,内置资源清单保存成功 : {saveFilePath}"); } } #endif } }