1、新建脚本"AssetBuildWindow.cs"放置Assets/Editor文件夹下
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEditor;
using UnityEngine;
public class AssetBuildWindow:EditorWindow
{
private string[] list;
private string warning;
private string Key = "";
private string btnname = "生成加密AB包";
GUIStyle warn = new GUIStyle();
private string dirpath = Application.streamingAssetsPath + "/AssetBundles";
[MenuItem("Tools/BuildAsset")]
static void AssetBuild()
{
Rect wr = new Rect(0, 0, 300, 200);
AssetBuildWindow window = (AssetBuildWindow)GetWindowWithRect(typeof(AssetBuildWindow), wr, true, "加密AB");
window.Show();
}
void OnGUI()
{
GUILayout.Space(20);
Key = EditorGUILayout.TextField("输入密钥:", Key);
GUILayout.Space(10);
if (GUILayout.Button("生成随机密钥", GUILayout.Width(200)))
{
string numChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
Key = "";
for (int i = 0; i < 16; i++)
{
Key += numChar.Substring(UnityEngine.Random.Range(0, 61), 1);
}
}
GUILayout.Space(20);
if (GUILayout.Button(btnname, GUILayout.Width(200)))
{
if (Key.Length != 16)
{
warn.normal.textColor = Color.red;
warning = $"请输入16位密钥";
return;
}
if (Directory.Exists(dirpath) == false)
{
Directory.CreateDirectory(dirpath);
}
if (Directory.GetFiles(dirpath).Length>0)
{
DelectDir(dirpath);
AssetDatabase.Refresh();
}
var temp = BuildPipeline.BuildAssetBundles(dirpath, BuildAssetBundleOptions.None, BuildTarget.Android);
list = temp.GetAllAssetBundles();
foreach (var item in list)
{
var bytes=File.ReadAllBytes($"{dirpath}/{item}");
var Encrypted= AesEncrypt(bytes, Key);
File.WriteAllBytes($"{dirpath}/{item}.Encrypted", Encrypted);
File.Delete($"{dirpath}/{item}");
}
AssetDatabase.Refresh();
btnname = "重新生成";
}
GUILayout.Space(20);
GUILayout.Label(warning, warn);
if (list!=null)
{
for (int i = 0; i < list.Length; i++)
{
warning = $"{list[i]}已生成\n";
}
}
}
public byte[] AesEncrypt(byte[] toEncryptArray, string key)
{
RijndaelManaged rm = new RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return resultArray;
}
/// <summary>
/// 删除文件夹下所有文件
/// </summary>
/// <param name="srcPath"></param>
public void DelectDir(string srcPath)
{
try
{
DirectoryInfo dir = new DirectoryInfo(srcPath);
FileSystemInfo[] fileinfo = dir.GetFileSystemInfos();
foreach (FileSystemInfo i in fileinfo)
{
if (i is DirectoryInfo)
{
DirectoryInfo subdir = new DirectoryInfo(i.FullName);
subdir.Delete(true);
}
else
{
File.Delete(i.FullName);
}
}
}
catch (Exception e)
{
}
}
}
2、场景设置AB包名
3、打AB包
4、加载时加载AB包:
新建脚本“ABundleLoading.cs”,代码如下
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class ABundleLoading : MonoBehaviour
{
public string sceneName;
//public Dialogs dialogs;
public UnityEvent clicktriggerEvent;
public AudioSource loadingaudio;
bool isclick = false;
#region 加载
public Image LoadingImage;
public Text LoadingText;
private float loadingSpeed = 1f;
private float targetValue;
private AsyncOperation operation;
#endregion
void Update()
{
if (operation != null)
{
targetValue = operation.progress;
if (operation.progress >= 0.9f)
{
targetValue = 1.0f;
}
if (targetValue != LoadingImage.fillAmount)
{
LoadingImage.fillAmount = Mathf.Lerp(LoadingImage.fillAmount, targetValue, Time.deltaTime * loadingSpeed);
if (Mathf.Abs(LoadingImage.fillAmount - targetValue) < 0.01f)
{
LoadingImage.fillAmount = targetValue;
}
}
//LoadingText.text = ((int)(LoadingImage.fillAmount * 100)).ToString() + "%";
if ((int)(LoadingImage.fillAmount * 100) == 100)
{
//AssetBundle.UnloadAllAssetBundles(true);
operation.allowSceneActivation = true;
}
}
Debug.Log(LoadingImage.fillAmount);
}
void Initial()
{
LoadingImage.fillAmount = 0.0f;
}
/// <summary>
/// 加载场景
/// </summary>
public void LoadingMain()
{
StartCoroutine(AsyncLoading());
}
/// <summary>
/// 异步加载场景
/// </summary>
/// <returns></returns>
IEnumerator AsyncLoading()
{
operation = SceneManager.LoadSceneAsync(sceneName);
SceneManager.sceneLoaded += SceneManager_sceneLoaded;
//阻止当前加载完成自动切换
operation.allowSceneActivation = false;
yield return operation;
}
private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
{
AssetBundle.UnloadAllAssetBundles(true);
}
IEnumerator Start()
{
yield return null;
UnityWebRequest webrequest = UnityWebRequest.Get(Application.streamingAssetsPath + "/AssetBundles/scene.Encrypted");//写入AB包名
//加进度条
yield return webrequest.SendWebRequest();
var debytes = AesDecrypt(webrequest.downloadHandler.data, "bjIxxwObUz1aP4e6");//填入密钥
var request2 = AssetBundle.LoadFromMemoryAsync(debytes);
yield return request2;
//SceneManager.LoadScene("CJ_CXGBZ");
//GetSceneData();
Initial();
LoadingMain();
//加进度条
}
public static byte[] AesDecrypt(byte[] toEncryptArray, string key)
{
RijndaelManaged rm = new RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return resultArray;
}
}
5、发布设置
发布时可不添加ab包场景