using System; using System.Collections.Generic; using System.IO; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; namespace AssetBundleHub { /// /// Fileから非同期でAssetBundleを読むクラス /// Readerという名前にすることで「Fileを触るクラス感」を出す。 /// public interface IAssetBundleReader { UniTask LoadFromFileAsync(string path, CancellationToken cancellationToken = default); } public static class DefaultAssetBundleReader { // NOTE: 暗号化機能作ったらこの中で分岐する想定 public static IAssetBundleReader New() => new AssetBundleReader(); } /// /// 暗号化されていないAssetBundleのLoader /// public class AssetBundleReader : IAssetBundleReader { public async UniTask LoadFromFileAsync(string path, CancellationToken cancellationToken = default) { var assetBundle = await AssetBundle.LoadFromFileAsync(path, 0).ToUniTask(cancellationToken: cancellationToken); return new AssetBundleRef(assetBundle); } } public class XORAssetBundleReader : IAssetBundleReader { byte[] keyBytes; public XORAssetBundleReader(byte[] keyBytes) { this.keyBytes = keyBytes; } // NOTE: streamはAssetBundleをUnloadした後にDisposeする必要がある // https://docs.unity3d.com/ja/2021.3/ScriptReference/AssetBundle.LoadFromStreamAsync.html public async UniTask LoadFromFileAsync(string path, CancellationToken cancellationToken = default) { AssetBundle assetBundle = null; var fs = new FileStream(path, FileMode.Open); var cs = new XORCryptStream(fs, keyBytes); assetBundle = await AssetBundle.LoadFromStreamAsync(cs, 0).ToUniTask(cancellationToken: cancellationToken); return new AssetBundleRef(assetBundle, new List() { cs, fs }); } } }