using System;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using Game.Config;
///
/// 构建ab包
///
public class AssetBundleMap : EditorWindow
{
///
/// shader都打入这个包
///
private const string ShaderAbName = "shader.unity3d";
///
/// 材质球都打入这个包
///
private const string MatAbName = "mat.unity3d";
///
/// 临时ab生成目录
///
private static readonly string TempAssetBundlePath = Application.dataPath + "/../assetbundle";
private static readonly string TempAssetBundleBakPath = Application.dataPath + "/../assetbundleBak";
private static readonly string DefaultBakDirPath = "Default";
private static readonly string ManifestFileExtension = ".manifest";
///
/// 使用lz4压缩
///
private static readonly BuildAssetBundleOptions BuildOptions = BuildAssetBundleOptions.DeterministicAssetBundle |
BuildAssetBundleOptions.ChunkBasedCompression;
///
/// 构建全部资源
///
[MenuItem("AssetBundle/BuildMap/BuildAllAssetBundles")]
public static void BuildAllAssetBundles(VersionCode resVersionCode)
{
Debug.Log("================ BuildAllAssetBundles Start================");
AssetDatabase.Refresh();
copyBakAssetsToAssetBundle();
AssetBundleUtil.CleanUnusedAB();
var buildMap = getAllBuildMap(true);
var abm = BuildPipeline.BuildAssetBundles(TempAssetBundlePath, buildMap, BuildOptions,
EditorUserBuildSettings.activeBuildTarget);
if (abm != null)
{
AssetBundleUtil.GetAllAssetsNameInAssetBundle(abm, resVersionCode);
copyAssetBundleToBakAssets();
copyBakAssetsToStreamingAssets();
Debug.Log("================ BuildAllAssetBundles Success================");
}
else
{
Debug.Log("================ BuildAllAssetBundles Fail================");
throw new Pack.PackException("BuildAssetBundles 失败");
}
}
///
/// 只打包lua相关的
/// 在只修改了lua代码,但是未修改资源的情况下使用
///
[MenuItem("AssetBundle/Build Map/Build Lua AssetBundles")]
public static void BuildLuaAssetBundles(VersionCode resVersionCode)
{
AssetDatabase.Refresh();
copyBakAssetsToAssetBundle();
AssetBundleUtil.CleanUnusedAB();
var buildMap = getLuaBuildMap(true);
var abm = BuildPipeline.BuildAssetBundles(TempAssetBundlePath, buildMap, BuildOptions,
EditorUserBuildSettings.activeBuildTarget);
if (abm == null)
{
throw new Pack.PackException("BuildAssetBundles 失败");
}
AssetBundleUtil.GetAllAssetsNameInAssetBundle(abm, resVersionCode);
copyAssetBundleToBakAssets();
copyBakAssetsToStreamingAssets();
}
private static void copyBakAssetsToAssetBundle()
{
if (Directory.Exists(TempAssetBundlePath))
{
Directory.Delete(TempAssetBundlePath, true);
}
Directory.CreateDirectory(TempAssetBundlePath);
string path = AssetsObscureUtil.GetUniqueValue();
string dirPath;
BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget;
if (!s_AssetbundleSavePaths.ContainsKey(buildTarget))
{
return;
}
if (string.IsNullOrEmpty(path))
{
dirPath = TempAssetBundleBakPath + s_AssetbundleSavePaths[buildTarget] + DefaultBakDirPath;
}
else
{
dirPath = TempAssetBundleBakPath + s_AssetbundleSavePaths[buildTarget] + path;
}
if (!Directory.Exists(dirPath))
{
return;
}
foreach (string file in Directory.GetFiles(dirPath))
{
string fileName = Path.GetFileName(file);
if (fileName == "assetbundle" || Path.GetExtension(file) == ".manifest")
{
string des = Path.Combine(TempAssetBundlePath, fileName);
File.Copy(file, des, true);
}
}
}
private static void copyAssetBundleToBakAssets()
{
string path = AssetsObscureUtil.GetUniqueValue();
string dirPath;
BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget;
if (!s_AssetbundleSavePaths.ContainsKey(buildTarget))
{
return;
}
if (string.IsNullOrEmpty(path))
{
dirPath = TempAssetBundleBakPath + s_AssetbundleSavePaths[buildTarget] + DefaultBakDirPath;
}
else
{
dirPath = TempAssetBundleBakPath + s_AssetbundleSavePaths[buildTarget] + path;
}
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
}
foreach (string file in Directory.GetFiles(TempAssetBundlePath))
{
string fileName = Path.GetFileName(file);
string des = Path.Combine(dirPath, fileName);
File.Copy(file, des, true);
}
}
///
/// 拷贝打包好的资源到目标目录
///
private static void copyBakAssetsToStreamingAssets()
{
string path = string.Empty;
if (Directory.Exists(Application.streamingAssetsPath))
{
foreach (var item in s_AssetbundleSavePaths)
{
path = Application.streamingAssetsPath + item.Value;
DeleteDirectoryAssets(path, true);
}
}
BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget;
if (!s_AssetbundleSavePaths.ContainsKey(buildTarget))
{
return;
}
string assetBundlePath = Application.streamingAssetsPath + s_AssetbundleSavePaths[buildTarget];
if (!Directory.Exists(assetBundlePath))
{
Directory.CreateDirectory(assetBundlePath);
}
path = AssetsObscureUtil.GetUniqueValue();
string dirPath;
if (string.IsNullOrEmpty(path))
{
dirPath = TempAssetBundleBakPath + s_AssetbundleSavePaths[buildTarget] + DefaultBakDirPath;
}
else
{
dirPath = TempAssetBundleBakPath + s_AssetbundleSavePaths[buildTarget] + path;
}
// 拷贝临时打包目录中的ab资源到对应的StreamingAssets目录下
foreach (string file in Directory.GetFiles(dirPath))
{
if (Path.GetExtension(file) != ".manifest")
{
string fileName = Path.GetFileName(file);
if (fileName == "assetbundle")
{
fileName = AssetsObscureUtil.GetABFileName(fileName);
LogABName("assetbundle", fileName);
}
else if (fileName == $"{ GetAssetsMappingName()}.bytes")
{
EncryptAssetsmapping(file, Path.Combine(assetBundlePath, fileName));
continue;
}
string des = Path.Combine(assetBundlePath, fileName);
File.Copy(file, des, true);
WriteMeaninglessDataToFile(des);
}
}
AssetDatabase.Refresh();
}
private static object GetAssetsMappingName()
{
#if UNITY_IOS
return "afi";
#else
return "assetsmapping";
#endif
}
private static Dictionary s_AssetbundleSavePaths = new Dictionary()
{
{BuildTarget.iOS, "/unityRes/"},
{BuildTarget.Android, "/AssetsAndroid/"},
{BuildTarget.StandaloneWindows64, "/AssetsPC/"},
{BuildTarget.WebGL, "/AssetsPC/"},
};
private static void EncryptAssetsmapping(string destPath, string filePath)
{
byte[] bytes = File.ReadAllBytes(destPath);
byte value;
int length = bytes.Length;
for (int i = 0, iMax = Mathf.FloorToInt(length * 0.5f); i < iMax; i += 2)
{
value = bytes[i];
bytes[i] = bytes[length - i - 1];
bytes[length - i - 1] = value;
}
using (var fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
fs.Write(bytes, 0, length);
}
}
///
/// 这个函数不能适配所有文件大小,理论上来说需要文件小于 (int.MaxValue / 2) byte
///
///
private static void WriteMeaninglessDataToFile(string filePath)
{
if (!AssetsObscureUtil.IsObscure()) return;
string fileName = Path.GetFileNameWithoutExtension(filePath);
ulong offset = AssetsObscureUtil.GetABOffset(fileName);
if (offset <= 0) return;
uint offsetMain = (uint)AssetsObscureUtil.GetObscureOffsetMin();
if (offset <= offsetMain) return;
byte[] bytes = File.ReadAllBytes(filePath);
int length = bytes.Length;
if (length <= 0) return;
byte[] offsetBytes = new byte[offset];
Array.Copy(bytes, offsetBytes, offsetMain);
byte[] md5Bytes;
using(var md5 = new MD5CryptoServiceProvider())
{
UTF8Encoding encoding = new UTF8Encoding(false);
md5Bytes = md5.ComputeHash(bytes);
}
uint md5Length = (uint)md5Bytes.Length;
int idx = 0;
for (ulong i = offsetMain + 1,
iMax = (offset - offsetMain);
i < iMax; i++)
{
idx = idx + md5Bytes[i % md5Length];
if (idx >= length - 1)
{
idx = idx - length + 1;
}
offsetBytes[i] = bytes[idx];
}
using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite))
{
fs.Write(offsetBytes, 0, (int)offset);
fs.Write(bytes, 0, length);
}
}
private struct AssetMap
{
///
/// key => ab name
/// value => asset names
///
public Dictionary> Maps;
///
/// 记录重复的情况
///
public HashSet AllAssets;
}
public static CheckResWindowInfo GetCheckResWindowInfo()
{
string path = "Assets/Editor/AssetBundle/CheckHotResWindownInfo.asset";
return AssetDatabase.LoadAssetAtPath(path);
}
public static Dictionary GetAbNameCfg()
{
Dictionary ret = new Dictionary();
string path = "Assets/Editor/AssetBundle/abname.csv";
TextAsset ta = AssetDatabase.LoadAssetAtPath(path);
CsvReader csvReader = new CsvReader(LanguageAssetBundleName.FileName_S(), ta.bytes);
LanguageAssetBundleName.OnCsvLoad(csvReader);
LanguageAssetBundleName.Foreach(it =>
{
ret.Add(it.BaseName, it);
//Debug.Log(it.BaseName);
});
LanguageAssetBundleName.Clear();
return ret;
}
///
/// 构建全部资源
///
///
///
private static AssetBundleBuild[] getAllBuildMap(bool showProcessBar)
{
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Start...", 0.1f);
AssetMap maps = new AssetMap();
maps.Maps = new Dictionary>(1024);
maps.AllAssets = new HashSet();
// 增加公共shader
addBuildAssetsCommon(maps, ShaderAbName, Constants.ShaderDir, "*.shader");
addBuildAssetsCommon(maps, ShaderAbName, Constants.ShaderDir, "*.shadervariants");
// font
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Font...", 0.2f);
addBuildAssetsFonts(maps);
addBuildAssetsCommon(maps, "commonmat.unity3d", Constants.CommonMaterialDir, "*.mat");
// config
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Config...", 0.3f);
addBuildAssetsCommon(maps, "config.unity3d", Constants.CsvConfig, "*.csv");
addBuildAssetsCommon(maps, "xml.unity3d", Constants.XmlConfig, "*.xml");
// audio
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Audio...", 0.4f);
addBuildAssetsBGM(maps);
addBuildAssetsCommon(maps, "UI_Audio.unity3d", Constants.UIAudioPath, "*.ogg");
addBuildAssetsCommon(maps, "Fight_Audio.unity3d", Constants.FightAudioPath, "*.ogg");
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Icons...", 0.5f);
addBuildAssetsIcons(maps);
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Camera...", 0.6f);
addBuildAssetsCamera(maps);
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Animator...", 0.65f);
addBuildAssetsAnimator(maps);
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Actor...", 0.7f);
addBuildAssetsActor(maps);
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Effect...", 0.75f);
addBuildAssetsEffect(maps);
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "UI...", 0.8f);
addBuildAssetsUI(maps);
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Scene...", 0.85f);
addBuildAssetsScene(maps);
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Lua...", 0.9f);
addBuildAssetsLua(maps);
Dictionary abnamecfg = GetAbNameCfg();
List bm = new List(maps.Maps.Count);
foreach (var items in maps.Maps)
{
AssetBundleBuild bundle = new AssetBundleBuild();
string abname = AssetsObscureUtil.GetABFileName(items.Key);
CheckResWindowInfo info = GetCheckResWindowInfo();
if (abnamecfg.ContainsKey(abname))
{
if (info.Language == BuildLanguage.cn)
{
bundle.assetBundleName = abnamecfg[abname].BaseName;
}
else
{
bundle.assetBundleName = abnamecfg[abname].En;
}
}
else
{
bundle.assetBundleName = abname;
}
bundle.assetNames = items.Value.ToArray();
LogABName(items.Key,bundle.assetBundleName);
if (bundle.assetNames.Length == 0)
{
Debug.LogWarning(items.Key + " empty assetNames");
continue;
}
bm.Add(bundle);
}
if (showProcessBar)
{
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Finish...", 1f);
EditorUtility.ClearProgressBar();
}
return bm.ToArray();
}
static string[] logNames = new string[] { "font.unity3d", "shader.unity3d", "UITexture_UILanuch.unity3d" , "UITexture_UILoading.unity3d", "UILanuch_uiprefab.unity3d", "UILoading_uiprefab.unity3d", "assetbundle" };
private static void LogABName(string name,string abname)
{
if (logNames.Contains(name))
{
Debug.Log($"=========== 包名:【{name}】 ab包名【{abname}】");
}
else
{
Debug.Log($"包名:【{name}】 ab包名【{abname}】");
}
}
///
/// 只构建lua相关的资源
///
///
///
private static AssetBundleBuild[] getLuaBuildMap(bool showProcessBar)
{
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Start...", 0.1f);
AssetMap maps = new AssetMap();
maps.Maps = new Dictionary>();
maps.AllAssets = new HashSet();
if (showProcessBar)
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Lua...", 0.9f);
addBuildAssetsCommon(maps, "config.unity3d", Constants.CsvConfig, "*.csv");
addBuildAssetsLua(maps);
List bm = new List(maps.Maps.Count);
foreach (var items in maps.Maps)
{
AssetBundleBuild bundle = new AssetBundleBuild();
bundle.assetBundleName = items.Key;
bundle.assetNames = items.Value.ToArray();
LogABName(items.Key, bundle.assetBundleName);
if (bundle.assetNames.Length == 0)
{
Debug.LogWarning(items.Key + " empty assetNames");
continue;
}
bm.Add(bundle);
}
if (showProcessBar)
{
EditorUtility.DisplayProgressBar("Generate Bundle Build Map", "Finish...", 1f);
EditorUtility.ClearProgressBar();
}
bm.Sort(assetBundleBuildSort);
return bm.ToArray();
}
private static AssetBundleBuildSort s_AssetBundleBuildSort = null;
private static AssetBundleBuildSort assetBundleBuildSort
{
get
{
if (s_AssetBundleBuildSort == null)
{
s_AssetBundleBuildSort = new AssetBundleBuildSort();
}
return s_AssetBundleBuildSort;
}
}
private class AssetBundleBuildSort : IComparer
{
public int Compare(AssetBundleBuild x, AssetBundleBuild y)
{
return string.Compare(x.assetBundleName, y.assetBundleName);
}
}
#region 处理各个模块的assetbundle
private static void addBuildAssetsCommon(AssetMap maps, string abName, string dir,
string filter)
{
string[] fileList = FileUtils.TraverseAllFiles(dir, filter);
for (int idx = 0; idx < fileList.Length; idx++)
{
string fullPath = fileList[idx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
if (relativePath.EndsWith(".meta")) continue;
addData(maps, abName, relativePath);
}
}
private static void addData(AssetMap maps, string assetBundleName, string assetName)
{
// 重复资源不能加入;按照资源初始化顺序写入
if (maps.AllAssets.Contains(assetName))
{
return;
}
maps.AllAssets.Add(assetName);
if (!maps.Maps.ContainsKey(assetBundleName))
{
maps.Maps[assetBundleName] = new HashSet();
}
maps.Maps[assetBundleName].Add(assetName);
}
private static void addBuildAssetsFonts(AssetMap maps)
{
string[] fileList = FileUtils.TraverseFiles(Constants.FontDir, "*.*");
for (int idx = 0; idx < fileList.Length; idx++)
{
string fullPath = fileList[idx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
if (relativePath.Contains(".meta")) continue;
addData(maps, "font.unity3d", relativePath);
}
string[] dirList = Directory.GetDirectories(Constants.FontDir);
for (int idx = 0; idx < dirList.Length; idx++)
{
string fullPath = dirList[idx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
string abName = relativePath.Replace("Assets/", "").Replace("/", "_") + ".unity3d";
string[] files = FileUtils.TraverseFiles(relativePath, "*.*");
for (int jdx = 0; jdx < files.Length; jdx++)
{
string filePathName = files[jdx];
if (filePathName.Contains(".meta")) continue;
string fileRelativePath = FileUtils.ExtractAssetRelativePath(filePathName);
addData(maps, abName, fileRelativePath);
}
}
}
private static void addBuildAssetsBGM(AssetMap maps)
{
string[] files = FileUtils.TraverseAllFiles(Constants.BGMAudioPath, "*.ogg");
for (int idx = 0; idx < files.Length; idx++)
{
string fullPath = files[idx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
string abName = FileUtils.RemoveExtension(FileUtils.ExtractPureName(relativePath)) + ".unity3d";
addData(maps, abName, relativePath);
}
}
private static void addBuildAssetsIcons(AssetMap maps)
{
string[] allAbNames = AssetDatabase.GetAllAssetBundleNames();
string[] dirs = Directory.GetDirectories(Constants.IconDir, "*", SearchOption.AllDirectories);
for (int idx = 0; idx < dirs.Length; idx++)
{
string dirName = dirs[idx];
string abName = FileUtils.ExtractPureName(dirName) + "_icons.unity3d";
if (allAbNames.Contains(abName))
{
AssetDatabase.RemoveAssetBundleName(abName, true);
}
string[] files = FileUtils.TraverseAllFiles(dirName, "*.png");
for (int jdx = 0; jdx < files.Length; jdx++)
{
string fullPath = files[jdx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
addData(maps, abName, relativePath);
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int kdx = 0; kdx < dependencyAssets.Length; kdx++)
{
string dependencyAssetName = dependencyAssets[kdx];
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType != "cs")
{
addData(maps, abName, dependencyAssetName);
}
}
}
}
}
private static void addBuildAssetsAnimator(AssetMap maps)
{
string[] dirs = Directory.GetDirectories(Constants.AnimatorPath, "*", SearchOption.AllDirectories);
for (int i = 0; i < dirs.Length; i++)
{
string dirName = dirs[i];
string[] files = FileUtils.TraverseAllFiles(dirName, "*.controller");
for (int idx = 0; idx < files.Length; idx++)
{
string fullPath = files[idx];
string fileName = FileUtils.ExtractPureName(fullPath);
string[] tempList = fileName.Split('_');
string abName = tempList[0] + "_animator.unity3d";
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
addData(maps, abName, relativePath);
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int jdx = 0; jdx < dependencyAssets.Length; jdx++)
{
string dependencyAssetName = dependencyAssets[jdx];
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType != "cs")
{
addData(maps, abName, dependencyAssetName);
}
}
}
}
}
private static void addBuildAssetsActor(AssetMap maps)
{
string[] dirs = Directory.GetDirectories(Constants.ModelPath, "*", SearchOption.AllDirectories);
for (int i = 0; i < dirs.Length; i++)
{
string dirName = dirs[i];
string abName = FileUtils.ExtractPureName(dirName) + ".unity3d";
string textureABName = FileUtils.ExtractPureName(dirName) + "_texture.unity3d";
string fbxABName = FileUtils.ExtractPureName(dirName) + "_model.unity3d";
string[] files = FileUtils.TraverseAllFiles(dirName, "*.prefab");
for (int idx = 0; idx < files.Length; idx++)
{
string fullPath = files[idx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
addData(maps, abName, relativePath);
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int jdx = 0; jdx < dependencyAssets.Length; jdx++)
{
string dependencyAssetName = dependencyAssets[jdx];
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType == "jpg" || fileType == "png" || fileType == "tga" || fileType == "tif" ||
fileType == "psd")
{
addData(maps, textureABName, dependencyAssetName);
}
else if (fileType == "fbx")
{
addData(maps, fbxABName, dependencyAssetName);
}
else if (fileType != "cs")
{
addData(maps, abName, dependencyAssetName);
}
}
}
}
}
private static void addBuildAssetsCamera(AssetMap maps)
{
string[] files = FileUtils.TraverseAllFiles("Assets/Content/Prefabs/Camera", "*.prefab");
for (int idx = 0; idx < files.Length; idx++)
{
string fullPath = files[idx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
string abName = "prefab_camera.unity3d";
addData(maps, abName, relativePath);
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int jdx = 0; jdx < dependencyAssets.Length; jdx++)
{
string dependencyAssetName = dependencyAssets[jdx];
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType != "cs")
{
addData(maps, abName, dependencyAssetName);
}
}
}
}
private static void addBuildAssetsEffect(AssetMap maps)
{
string effectTextureABName = "effect_texture.unity3d";
string effectAnimABName = "effect_dep.unity3d";
string abName = "effect.unity3d";
string[] dirs = Directory.GetDirectories(Constants.EffectPath, "*", SearchOption.AllDirectories);
for (int idx = 0; idx < dirs.Length; idx++)
{
string dirName = dirs[idx];
string[] fileList = FileUtils.TraverseAllFiles(dirName, "*.prefab");
for (int jdx = 0; jdx < fileList.Length; jdx++)
{
string fullPath = fileList[jdx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
addData(maps, abName, relativePath);
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int kdx = 0; kdx < dependencyAssets.Length; kdx++)
{
string dependencyAssetName = dependencyAssets[kdx];
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType == "jpg" || fileType == "png" || fileType == "tga" || fileType == "tif" ||
fileType == "psd")
{
addData(maps, effectTextureABName, dependencyAssetName);
}
else if (fileType != "cs")
{
addData(maps, effectAnimABName, dependencyAssetName);
}
}
}
}
}
private static void addBuildAssetsUI(AssetMap maps)
{
addBuildAssets3DUIPrefab(maps);
addBuildAssetsUIPrefab(maps);
}
private static void addBuildAssets3DUIPrefab(AssetMap maps)
{
string[] allAbNames = AssetDatabase.GetAllAssetBundleNames();
string[] dirs = Directory.GetDirectories(Constants.UI3DPath, "*", SearchOption.AllDirectories);
for (int idx = 0; idx < dirs.Length; idx++)
{
string dirName = dirs[idx];
string abName = FileUtils.ExtractPureName(dirName) + "_3duiprefab.unity3d";
string textureABName = FileUtils.ExtractPureName(dirName) + "_3duiprefab_texture.unity3d";
if (allAbNames.Contains(abName))
{
AssetDatabase.RemoveAssetBundleName(abName, true);
}
string[] files = FileUtils.TraverseAllFiles(dirName, "*.prefab");
for (int jdx = 0; jdx < files.Length; jdx++)
{
string fullPath = files[jdx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
addData(maps, abName, relativePath);
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int kdx = 0; kdx < dependencyAssets.Length; kdx++)
{
string dependencyAssetName = dependencyAssets[kdx];
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType == "jpg" || fileType == "png" || fileType == "tga" || fileType == "tif" ||
fileType == "psd")
{
addData(maps, textureABName, dependencyAssetName);
}
else if (fileType != "cs")
{
addData(maps, abName, dependencyAssetName);
}
}
}
}
}
private static void addBuildAssetsUIPrefab(AssetMap maps)
{
string[] allAbNames = AssetDatabase.GetAllAssetBundleNames();
string[] dirs = Directory.GetDirectories(Constants.UIPath, "*", SearchOption.AllDirectories);
for (int idx = 0; idx < dirs.Length; idx++)
{
string dirName = dirs[idx];
string dirRelativeName = FileUtils.ExtractAssetRelativePath(dirName);
string abName = "";
if (dirRelativeName == Constants.UICommonPath)
{
abName = "prefabsuicommon.unity3d";
}
else
{
abName = FileUtils.ExtractPureName(dirName) + "_uiprefab.unity3d";
}
if (allAbNames.Contains(abName))
{
AssetDatabase.RemoveAssetBundleName(abName, true);
}
string[] files = FileUtils.TraverseAllFiles(dirName, "*.prefab");
for (int jdx = 0; jdx < files.Length; jdx++)
{
string fullPath = files[jdx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
addData(maps, abName, relativePath);
string rootParent;
FileUtils.ExtractParent(relativePath, out rootParent);
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int kdx = 0; kdx < dependencyAssets.Length; kdx++)
{
string dependencyAssetName = dependencyAssets[kdx];
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType == "jpg" || fileType == "png" || fileType == "tga" || fileType == "tif" ||
fileType == "psd")
{
string parent;
FileUtils.ExtractParent(dependencyAssetName, out parent);
parent = FileUtils.ExtractPureName(parent);
string uiTextureABName = "UITexture_" + parent + ".unity3d";
addData(maps, uiTextureABName, dependencyAssetName);
}
else if (fileType == "prefab")
{
string parent;
FileUtils.ExtractParent(dependencyAssetName, out parent);
if (parent.StartsWith(Constants.UIPath))
{
if (rootParent == parent)
{
addData(maps, abName, dependencyAssetName);
}
}
else
{
addData(maps, abName, dependencyAssetName);
}
}
else if (fileType != "cs")
{
addData(maps, abName, dependencyAssetName);
}
}
}
}
}
private static void addBuildAssetsScene(AssetMap maps)
{
string[] fileList = Directory.GetFiles(Constants.ScenePath, "*.unity", SearchOption.AllDirectories);
for (int idx = 0; idx < fileList.Length; idx++)
{
string fullPath = fileList[idx];
if (fullPath.Contains("UIScene") || fullPath.Contains("meta") || fullPath.Contains("SceneCG") ||
fullPath.Replace('\\', '/').Contains("Scene/Other") || fullPath.Contains("WasteAsset") ||
fullPath.Contains("Building"))
continue;
if (fullPath.Contains("game.unity") || fullPath.Contains("Loading.unity"))
{
continue;
}
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
string abName = FileUtils.RemoveExtension(FileUtils.ExtractPureName(relativePath)) + ".unity3d";
addData(maps, abName, relativePath);
string scenePrefabABName =
FileUtils.RemoveExtension(FileUtils.ExtractPureName(relativePath)) + "_prefab.unity3d";
string sceneTextureABName =
FileUtils.RemoveExtension(FileUtils.ExtractPureName(relativePath)) + "_texture.unity3d";
string sceneOtherABName =
FileUtils.RemoveExtension(FileUtils.ExtractPureName(relativePath)) + "_other.unity3d";
string lightmapABName = FileUtils.RemoveExtension(FileUtils.ExtractPureName(relativePath)) + "_lm.unity3d";
string[] dependencyAssets = AssetDatabase.GetDependencies(relativePath);
for (int kdx = 0; kdx < dependencyAssets.Length; kdx++)
{
string dependencyAssetName = dependencyAssets[kdx];
if (dependencyAssetName.Contains("Lightmap-") ||
dependencyAssetName.Contains("LightingData") ||
dependencyAssetName.Contains("ReflectionProbe"))
{
addData(maps, lightmapABName, dependencyAssetName);
}
else if (dependencyAssetName.Contains("PostProcessing") && !dependencyAssetName.Contains(".cs"))
{
if (dependencyAssetName.Contains(".shader"))
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else
{
addData(maps, "PostProcessing.unity3d", dependencyAssetName);
}
}
else
{
string fileType = dependencyAssetName.Substring(dependencyAssetName.LastIndexOf('.') + 1);
fileType = fileType.ToLower();
if (fileType == "shader")
{
addData(maps, ShaderAbName, dependencyAssetName);
}
else if (fileType == "mat")
{
addData(maps, MatAbName, dependencyAssetName);
}
else if (fileType == "prefab")
{
if (dependencyAssetName.Contains("Scenes/Scene_common"))
{
string sCommonAb = "scene_common_prefab.unity3d";
addData(maps, sCommonAb, dependencyAssetName);
}
else
{
addData(maps, scenePrefabABName, dependencyAssetName);
}
}
else if (fileType == "png" || fileType == "tga" || fileType == "jpg" || fileType == "tif" ||
fileType == "psd")
{
if (dependencyAssetName.Contains("Scenes/Scene_common"))
{
string sCommonAb = "scene_common_texture.unity3d";
addData(maps, sCommonAb, dependencyAssetName);
}
else
{
addData(maps, sceneTextureABName, dependencyAssetName);
}
}
else if (fileType != "cs")
{
if (dependencyAssetName.Contains("Scenes/Scene_common"))
{
string sCommonAb = "scene_common_other.unity3d";
addData(maps, sCommonAb, dependencyAssetName);
}
else
{
addData(maps, sceneOtherABName, dependencyAssetName);
}
}
}
}
}
}
#endregion
#region 处理lua文件
private static void addBuildAssetsLua(AssetMap maps)
{
CopyLuaAssets(Constants.LuaDir, Constants.ABLuaDir);
CopyLuaAssets(Constants.LuaLogicDir, Constants.ABLuaLogicDir, true);
CopyLuaAssets(Constants.LuaPbDir, Constants.ABLuaPbDir);
CopyLuaAssets(Constants.PubSec, Constants.ABPubsec);
AssetDatabase.Refresh();
ProcessConfigAndLua(maps);
}
private static void CopyLuaAssets(string sourceDir, string destDir, bool optimize = false)
{
string path = Application.dataPath;
path = path.Replace("Assets", "");
string sourceAbsDir = Path.Combine(path, sourceDir);
string destAbsDir = Path.Combine(path, destDir);
HashSet sourceFiles = getAllFilesPathEX(sourceAbsDir);
HashSet destFiles = getAllFilesPathEX(destAbsDir);
// 删除不再需要的文件
foreach (var destFile in destFiles)
{
string sourceFile = destFile.Replace(destAbsDir, sourceAbsDir);
string fileName = Path.GetExtension(sourceFile);
if (fileName.ToLower() == ".txt")
{
string ext = Path.GetExtension(fileName);
if (s_ValidExtMap.Contains(ext))
{
sourceFile = sourceFile.Remove(sourceFile.Length - 4);
}
}
if (!sourceFiles.Contains(sourceFile))
{
File.Delete(destFile);
string metaFilePath = destFile + ".meta";
if (File.Exists(metaFilePath))
{
File.Delete(metaFilePath);
}
string folder = Path.GetDirectoryName(destFile);
DeleteDirectoryAssets(folder);
}
}
// 替换新文件
foreach (var filePath in sourceFiles)
{
string destFilePath = filePath.Replace(sourceAbsDir, destAbsDir);
string destFolder = Path.GetDirectoryName(destFilePath);
if (!Directory.Exists(destFolder))
{
Directory.CreateDirectory(destFolder);
}
destFilePath = destFilePath + ".txt";
if (!File.Exists(destFilePath))
{
File.Copy(filePath, destFilePath, true);
if (optimize && destFilePath.Contains("_Generate"))
{
string[] lines = FileSystem.ReadFileLines(destFilePath);
List contents = new List(lines);
for (var i = contents.Count - 1; i >= 0; --i)
{
if (contents[i].StartsWith("---@") || contents[i].Equals(""))
{
contents.RemoveAt(i);
}
}
File.WriteAllLines(destFilePath, contents.ToArray());
}
}
else
{
if (optimize && destFilePath.Contains("_Generate"))
{
string[] lines1 = FileSystem.ReadFileLines(filePath);
List contents = new List(lines1);
for (var i = contents.Count - 1; i >= 0; --i)
{
if (contents[i].StartsWith("---@") || contents[i].Equals(""))
{
contents.RemoveAt(i);
}
}
lines1 = contents.ToArray();
string[] lines2 = FileSystem.ReadFileLines(destFilePath);
bool diff = (lines1.Length != lines2.Length);
if (!diff)
{
for (var i = lines1.Length - 1; i >= 0; i--)
{
if (lines1[i] != lines2[i])
{
diff = true;
continue;
}
}
}
if (diff)
File.WriteAllLines(destFilePath, lines1);
}
else
{
string content1 = File.ReadAllText(filePath);
string content2 = File.ReadAllText(destFilePath);
if (content1 != content2)
{
File.Copy(filePath, destFilePath, true);
}
}
}
}
}
private static void DeleteDirectoryAssets(string dir, bool forceDelete = false)
{
if (!Directory.Exists(dir)) return;
var ls = Directory.GetFileSystemEntries(dir);
if (forceDelete || ls == null || ls.Length <= 0)
{
Directory.Delete(dir, true);
if (dir.EndsWith("/") || dir.EndsWith("\\"))
{
dir = dir.Substring(0, dir.Length - 1);
}
string metaFilePath = dir + ".meta";
if (File.Exists(metaFilePath))
{
File.Delete(metaFilePath);
}
string folder = Path.GetDirectoryName(dir);
DeleteDirectoryAssets(folder);
}
}
private static void CopyLuaAsset(string dir)
{
string path = Application.dataPath;
path = Path.Combine(path.Replace("Assets", ""), dir);
List files = FileSystem.getAllFilesPathEX(path);
foreach (string fileName in files)
{
string destName = fileName.Insert(fileName.IndexOf("Assets/") + 7, "Content/");
string destFolder = Path.GetDirectoryName(destName);
if (!Directory.Exists(destFolder))
{
Directory.CreateDirectory(destFolder);
}
File.Copy(fileName, destName + ".txt", true);
if (dir.CompareTo(Constants.LuaLogicDir) == 0 && destName.Contains("_Generate"))
{
string[] lines = FileSystem.ReadFileLines(destName + ".txt");
List contents = new List(lines);
for (var i = contents.Count - 1; i >= 0; --i)
{
if (contents[i].StartsWith("---@") || contents[i].Equals(""))
{
contents.RemoveAt(i);
}
}
File.WriteAllLines(destName + ".txt", contents.ToArray());
}
}
}
static void ProcessConfigAndLua(AssetMap maps)
{
string luaABName = Constants.LuaDir.Replace("Assets", "").Replace("Content", "").Replace("/", "").ToLower();
string luaLogicABName = Constants.LuaLogicDir.Replace("Assets", "").Replace("Content", "").Replace("/", "")
.ToLower();
string luaPbABName = Constants.LuaPbDir.Replace("Assets", "").Replace("Content", "").Replace("/", "").ToLower();
string pubSecABName = Constants.PubSec.Replace("Assets", "").Replace("Content", "").Replace("/", "").ToLower();
string[] allAbNames = AssetDatabase.GetAllAssetBundleNames();
if (allAbNames.Contains(luaABName))
AssetDatabase.RemoveAssetBundleName(luaABName, true);
if (allAbNames.Contains(luaLogicABName))
AssetDatabase.RemoveAssetBundleName(luaLogicABName, true);
if (allAbNames.Contains(luaPbABName))
AssetDatabase.RemoveAssetBundleName(luaPbABName, true);
if (allAbNames.Contains(pubSecABName))
AssetDatabase.RemoveAssetBundleName(pubSecABName, true);
ProcessConfigAndLua(maps, Constants.ABLuaPbDir, luaPbABName);
ProcessConfigAndLua(maps, Constants.ABLuaDir, luaABName);
ProcessConfigAndLua(maps, Constants.ABLuaLogicDir, luaLogicABName);
ProcessConfigAndLua(maps, Constants.ABPubsec, pubSecABName);
}
static void ProcessConfigAndLua(AssetMap maps, string dir, string abName)
{
List fileList = FileSystem.getAllFilesPathEX(dir);
for (int idx = 0; idx < fileList.Count; idx++)
{
string fullPath = fileList[idx];
string relativePath = FileUtils.ExtractAssetRelativePath(fullPath);
if (relativePath.Contains("/Pb/") && dir != Constants.ABLuaPbDir) continue;
addData(maps, abName + ".unity3d", relativePath);
}
}
#endregion
private static HashSet s_ValidExtMap = new HashSet()
{
".prefab", ".txt", ".xml", ".txt", ".lua", ".csv", ".ogg", ".wav", ".ttf", ".bytes", ".pb",
};
private static HashSet getAllFilesPathEX(string path, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories)
{
HashSet all = new HashSet();
if (!Directory.Exists(path))
{
return all;
}
string[] allFiles = Directory.GetFiles(path, searchPattern, searchOption);
for (int j = 0; j < allFiles.Length; ++j)
{
string fileName = allFiles[j];
string ext = Path.GetExtension(fileName);
if (string.IsNullOrEmpty(ext)) continue;
ext = ext.ToLower();
if (s_ValidExtMap.Contains(ext))
{
all.Add(fileName.Replace('\\', '/'));
}
}
return all;
}
}