首先需要的是一个编辑器扩展,运用到在编辑器里边创建一个PictureAssetBundle打包,然后将PictureBundle打包在TempStreamingAsset下,然后将TempStreamingAsset下的Assetbundle复制到StreamingAsset下,然后给AssetBundle加解密,等下具体代码附上
public static class ImageEncryption { private static string TEMP_ASSETBUNDLE_PATH = Application.dataPath + "/TempAssetBundle"; private static string ASSETBUNDLE_NAME = "Picture.assetbundle"; private static string EncryptKey = "SayYes"; //将纹理打包成Assetbundle [MenuItem("编辑器扩展关于图集/创建PictureBundle")] public static void CreateImageAssetBundle() { Listbuilds = new List (); AssetBundleBuild build1 = new AssetBundleBuild(); build1.assetBundleName = ASSETBUNDLE_NAME; build1.assetNames = new string[] { "Assets/TestTest/8.png", "Assets/TestTest/9.png","Assets/TestTest/10.png","Assets/TestTest/11.png","Assets/TestTest/12.png","Assets/TestTest/13.png","Assets/TestTest/14.png" }; builds.Add(build1); if (!Directory.Exists(TEMP_ASSETBUNDLE_PATH)) Directory.CreateDirectory(TEMP_ASSETBUNDLE_PATH); if (BuildPipeline.BuildAssetBundles(TEMP_ASSETBUNDLE_PATH, builds.ToArray(), BuildAssetBundleOptions.None, BuildTarget.Android)) { Debug.Log("资源打包成功"); } UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); } [MenuItem("编辑器扩展关于图集/拷贝PictureBundle")] //纹理图集加密,并拷贝到StreamingAssets文件夹里 public static void EncryptExPackImage() { string assetbundle_file_path = Path.Combine(TEMP_ASSETBUNDLE_PATH, ASSETBUNDLE_NAME.ToLower()); byte[] bytes = File.ReadAllBytes(assetbundle_file_path); //字节数组加密,这个可以自己网上搜一下相应的加密算法 byte[] encryptedBytes = AesMgr.AESEncrypt(bytes,EncryptKey); string targetPath = Application.streamingAssetsPath; if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath); File.WriteAllBytes(targetPath + "/" + ASSETBUNDLE_NAME.ToLower(), encryptedBytes); UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); } }
然后在Mono层解密调用,这个可以做在一个场景里边,然后那个场景加载完全部的数据,保存在一个静态类里边,下边简单附上代码,本来那个dictionary应该是用public static 生命才对
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; using System; public class LoadAssetBundle : MonoBehaviour { private bool isTextureLoadFinish; private Dictionaryspritecatch = new Dictionary (); public Image imageOne, imageTwo; public string AssetbundleName = "picture"; private string EncryptKey = "SayYes"; // Start is called before the first frame update void Start() { StartCoroutine(LoadImageByRequestUrl()); StartCoroutine(ShowImage()); } private IEnumerator LoadImageByRequestUrl() { string path = " "; #if UNITY_ANDROID && !UNITY_EDITOR path = Application.streamingAssetsPath + "/" + AssetbundleName; #else path = "file://" + Application.streamingAssetsPath + "/" + AssetbundleName; #endif var uwr = UnityWebRequest.Get(path); yield return uwr.SendWebRequest(); byte[] decryptedBytes = AesMgr.AESDecrypt(uwr.downloadHandler.data,EncryptKey); AssetBundle bundleOne = AssetBundle.LoadFromMemory(decryptedBytes); Sprite[] Sprites = bundleOne.LoadAllAssets (); foreach(Sprite sprite in Sprites) { try { if (!spritecatch.ContainsKey(sprite.name)) spritecatch.Add(sprite.name, sprite); else Debug.LogError("List is already Contains" + sprite.name); } catch(Exception e) { Debug.LogError("sp.name" + e); } } isTextureLoadFinish = true; } private IEnumerator ShowImage() { yield return new WaitUntil(() => { return isTextureLoadFinish; }); imageOne.sprite = spritecatch["8"]; imageTwo.sprite = spritecatch["9"]; } // Update is called once per frame }
然后我自己写了一个AesMgr关于加解密资源的
using UnityEngine; using System.Collections; using MyGameFrameWork; using System.IO; using System.Text; using System; using System.Security.Cryptography; public class AesMgr :BaseManager{ private static string AESHead = "AESEncrypt"; /// /// 文件加密,传入文件路径 /// /// /// /// public static void AESFileEncrypt(string path, string EncrptyKey) { if (!File.Exists(path)) { Debug.Log("不存在该文件"); return; } try { Debug.Log("执行"); using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { if (fs != null) { //读取字节头,判断是否已经加密过了 byte[] headBuff = new byte[10]; fs.Read(headBuff, 0, headBuff.Length); string headTag = Encoding.UTF8.GetString(headBuff); if (headTag == AESHead) { #if UNITY_EDITOR Debug.Log(path + "已经加密过了!"); #endif return; } //加密并且写入字节头 fs.Seek(0, SeekOrigin.Begin); byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, Convert.ToInt32(fs.Length)); fs.Seek(0, SeekOrigin.Begin); fs.SetLength(0); byte[] headBuffer = Encoding.UTF8.GetBytes(AESHead); fs.Write(headBuffer, 0, headBuffer.Length); byte[] EncBuffer = AESEncrypt(buffer, EncrptyKey); fs.Write(EncBuffer, 0, EncBuffer.Length); } } } catch (Exception e) { Debug.LogError(e); } } ////// 文件解密,传入文件路径(会改动加密文件,不适合运行时) /// /// /// public static void AESFileDecrypt(string path, string EncrptyKey) { if (!File.Exists(path)) { Debug.Log("文件不存在"); return; } try { using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { if (fs != null) { Debug.Log("开始解密"); byte[] headBuff = new byte[10]; fs.Read(headBuff, 0, headBuff.Length); string headTag = Encoding.UTF8.GetString(headBuff); if (headTag == AESHead) { byte[] buffer = new byte[fs.Length - headBuff.Length]; fs.Read(buffer, 0, Convert.ToInt32(fs.Length - headBuff.Length)); fs.Seek(0, SeekOrigin.Begin); fs.SetLength(0); byte[] DecBuffer = AESDecrypt(buffer, EncrptyKey); fs.Write(DecBuffer, 0, DecBuffer.Length); Debug.Log("解密成功"); } } } } catch (Exception e) { Debug.LogError(e); } } ////// 文件界面,传入文件路径,返回字节 /// ///public static byte[] AESFileByteDecrypt(string path, string EncrptyKey) { if (!File.Exists(path)) { return null; } byte[] DecBuffer = null; try { using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (fs != null) { byte[] headBuff = new byte[10]; fs.Read(headBuff, 0, headBuff.Length); string headTag = Encoding.UTF8.GetString(headBuff); if (headTag == AESHead) { byte[] buffer = new byte[fs.Length - headBuff.Length]; fs.Read(buffer, 0, Convert.ToInt32(fs.Length - headBuff.Length)); DecBuffer = AESDecrypt(buffer, EncrptyKey); } } } } catch (Exception e) { Debug.LogError(e); } return DecBuffer; } /// /// AES 加密(高级加密标准,是下一代的加密算法标准,速度快,安全级别高,目前 AES 标准的一个实现是 Rijndael 算法) /// /// 待加密密文 /// 加密密钥 public static string AESEncrypt(string EncryptString, string EncryptKey) { return Convert.ToBase64String(AESEncrypt(Encoding.Default.GetBytes(EncryptString), EncryptKey)); } ////// AES 加密(高级加密标准,是下一代的加密算法标准,速度快,安全级别高,目前 AES 标准的一个实现是 Rijndael 算法) /// /// 待加密密文 /// 加密密钥 public static byte[] AESEncrypt(byte[] EncryptByte, string EncryptKey) { if (EncryptByte.Length == 0) { throw (new Exception("明文不得为空")); } if (string.IsNullOrEmpty(EncryptKey)) { throw (new Exception("密钥不得为空")); } byte[] m_strEncrypt; byte[] m_btIV = Convert.FromBase64String("Rkb4jvUy/ye7Cd7k89QQgQ=="); byte[] m_salt = Convert.FromBase64String("gsf4jvkyhye5/d7k8OrLgM=="); Rijndael m_AESProvider = Rijndael.Create(); try { MemoryStream m_stream = new MemoryStream(); PasswordDeriveBytes pdb = new PasswordDeriveBytes(EncryptKey, m_salt); ICryptoTransform transform = m_AESProvider.CreateEncryptor(pdb.GetBytes(32), m_btIV); CryptoStream m_csstream = new CryptoStream(m_stream, transform, CryptoStreamMode.Write); m_csstream.Write(EncryptByte, 0, EncryptByte.Length); m_csstream.FlushFinalBlock(); m_strEncrypt = m_stream.ToArray(); m_stream.Close(); m_stream.Dispose(); m_csstream.Close(); m_csstream.Dispose(); } catch (IOException ex) { throw ex; } catch (CryptographicException ex) { throw ex; } catch (ArgumentException ex) { throw ex; } catch (Exception ex) { throw ex; } finally { m_AESProvider.Clear(); } return m_strEncrypt; } ////// AES 解密(高级加密标准,是下一代的加密算法标准,速度快,安全级别高,目前 AES 标准的一个实现是 Rijndael 算法) /// /// 待解密密文 /// 解密密钥 public static string AESDecrypt(string DecryptString, string DecryptKey) { return Convert.ToBase64String(AESDecrypt(Encoding.Default.GetBytes(DecryptString), DecryptKey)); } ////// AES 解密(高级加密标准,是下一代的加密算法标准,速度快,安全级别高,目前 AES 标准的一个实现是 Rijndael 算法) /// /// 待解密密文 /// 解密密钥 public static byte[] AESDecrypt(byte[] DecryptByte, string DecryptKey) { if (DecryptByte.Length == 0) { throw (new Exception("密文不得为空")); } if (string.IsNullOrEmpty(DecryptKey)) { throw (new Exception("密钥不得为空")); } byte[] m_strDecrypt; byte[] m_btIV = Convert.FromBase64String("Rkb4jvUy/ye7Cd7k89QQgQ=="); byte[] m_salt = Convert.FromBase64String("gsf4jvkyhye5/d7k8OrLgM=="); Rijndael m_AESProvider = Rijndael.Create(); try { MemoryStream m_stream = new MemoryStream(); PasswordDeriveBytes pdb = new PasswordDeriveBytes(DecryptKey, m_salt); ICryptoTransform transform = m_AESProvider.CreateDecryptor(pdb.GetBytes(32), m_btIV); CryptoStream m_csstream = new CryptoStream(m_stream, transform, CryptoStreamMode.Write); m_csstream.Write(DecryptByte, 0, DecryptByte.Length); m_csstream.FlushFinalBlock(); m_strDecrypt = m_stream.ToArray(); m_stream.Close(); m_stream.Dispose(); m_csstream.Close(); m_csstream.Dispose(); } catch (IOException ex) { throw ex; } catch (CryptographicException ex) { throw ex; } catch (ArgumentException ex) { throw ex; } catch (Exception ex) { throw ex; } finally { m_AESProvider.Clear(); } return m_strDecrypt; } }
然后用这个类来加解密AssetBundle,大概就这样了