public class ABTool : EditorWindow
{
static string dllpath = Application.dataPath + "/../" + HybridCLRSettings.Instance.hotUpdateDllCompileOutputRootDir;
public static List<string> AOTMetaAssemblyNames { get; } = new List<string>()
{
"mscorlib.dll",
"System.dll",
"System.Core.dll",
};
[MenuItem("ABTool/生成AB包")]
public static void CreatAB()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
//找到对应目录
DirectoryInfo direction = new DirectoryInfo(dllpath + "/" + target);
//获取目录下所有文件
FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);
//把所有dll文件拷贝到s目录下
foreach (var item in files)
{
if (item.Name.EndsWith(".dll"))
{
string dllPath = $"{dllpath + "/" + target}/{item.Name}";
string dllBytesPath = $"{Application.streamingAssetsPath }/{item.Name}.bytes";
File.Copy(dllPath, dllBytesPath, true);
Debug.Log($"hotfix dll{dllPath}->{ dllBytesPath}");
}
}
//预制体
List<AssetBundleBuild> abs = new List<AssetBundleBuild>();
//找到预制体目录下的所有目录
AddABPath(abs, $"{Application.dataPath}/Prefabs/");
AddABPath(abs, $"{Application.dataPath}/Resources/");
//构建AB包放到S目录下
BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, abs.ToArray(), BuildAssetBundleOptions.None, target);
//加载补充元数据
CopyAOTAssembliesToStreamingAssets();
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
}
public static void CopyAOTAssembliesToStreamingAssets()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string aotAssembliesSrcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
string aotAssembliesDrcDir = Application.streamingAssetsPath;
foreach (var dll in AOTMetaAssemblyNames)
{
string srcDllPath = $"{aotAssembliesSrcDir}/{dll}";
if (!File.Exists(srcDllPath))
{
Debug.LogError($"ab中添加AOT补充元数据dll:{srcDllPath}时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成,因此需要你先构建一次游戏App后再打包。");
continue;
}
string dllBytesPath = $"{aotAssembliesDrcDir}/{dll}.bytes";
File.Copy(srcDllPath, dllBytesPath, true);
Debug.Log($"[CopyAOTAssembliesToStreamingAssets] copy AOT dll{srcDllPath}->{dllBytesPath}");
}
}
public static void AddABPath(List<AssetBundleBuild> abs, string path)
{
DirectoryInfo directionInfo = new DirectoryInfo(path);//用于创建 移动..目录
DirectoryInfo[] directions = directionInfo.GetDirectories();//返回子目录
//每个目录打一个AB包
for (int i = 0; i < directions.Length; i++)
{
List<string> prefabAssets = new List<string>();
Debug.Log("打包文件夹:" + directions[i].Name);
FileInfo[] fileinfos = directions[i].GetFiles("*", SearchOption.AllDirectories);
Debug.Log("目录下文件夹个数:" + fileinfos.Length);
foreach (var item in fileinfos)
{
if (item.Name.EndsWith(".meta"))
{
continue;
}
Debug.Log("打包文件:" + item.Name);
prefabAssets.Add(item.FullName.Replace("\\", "/"));
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
}
AssetBundleBuild PrefabsAb = new AssetBundleBuild
{
assetBundleName = directions[i].Name,
assetNames = prefabAssets.Select(s => ToReleateAssetPath(s)).ToArray()
};
abs.Add(PrefabsAb);
}
}
public static string ToReleateAssetPath(string s)
{
string path = s.Substring(s.IndexOf("Assets/"));
Debug.Log(path);
return path;
}
[MenuItem("ABTool/生成version")]//版本
public static void MakeVersion()
{
string json = AssetDatabase.LoadAssetAtPath<TextAsset>("Assets/Resources/Config/config.json").text;
Config config = JsonConvert.DeserializeObject<Config>(json);
List<VersionData> versionDatas = new List<VersionData>();
//第一条是假数据,用力判断是否需要热更新
VersionData version = new VersionData();
//判断使用测试版还是正式版热更新
config.upid++;
version.abName = config.isBate ? config.hotPath_Bate : config.hotPath;
version.len = config.upid;//更新号
version.md5 = config.version;//版本号
versionDatas.Add(version);
//重新写入
json = JsonConvert.SerializeObject(config);
File.WriteAllText(Application.dataPath+ "/Resources/Config/config.json", json);
//找到s目录下所有文件
string[] files = Directory.GetFiles(Application.streamingAssetsPath, ".", SearchOption.AllDirectories);
foreach (var item in files)
{
//取后缀名
string extensionName = Path.GetExtension(item);
//排除.meat和.manifest文件
if (extensionName.Contains("meta") || extensionName.Contains("manifest")) continue;
Debug.Log(item);
string abName = item.Replace(Application.dataPath, "Assets");
abName = abName.Replace("\\", "/");
string assetBundleName = "";
assetBundleName = abName.Replace("Assets/StreamingAssets/", string.Empty);
VersionData versionData = new VersionData();
versionData.abName = assetBundleName;
versionData.len = File.ReadAllText(item).Length;
versionData.md5 = FileMD5(item);
versionDatas.Add(versionData);
}
//写入文件
string versionInfo = JsonConvert.SerializeObject(versionDatas);
File.WriteAllText(Application.streamingAssetsPath + "/version.txt", versionInfo, Encoding.UTF8);
AssetDatabase.Refresh();
Debug.Log("version.txt创建成功");
}
static string FileMD5(string filepath)
{
FileStream fileStream = new FileStream(filepath, FileMode.Open);
MD5 mD5 = new MD5CryptoServiceProvider();
byte[] bytes = mD5.ComputeHash(fileStream);
StringBuilder sb = new StringBuilder();
for (int i = 0; i <bytes.Length; i++)
{
sb.Append(bytes[i].ToString("x2"));
}
return sb.ToString();
}
}
HybridCLR 热更新(打AB包)练习
最新推荐文章于 2024-03-20 14:06:39 发布