Unity 5.0 AB 系统
总体来说简单分为这几步(文章会给代码示例)
- 工程资源ab命名
- Lua 文件特殊处理转为txt文件,并且为其ab命名
- 打包所有ab资源
- 真机测试本地ab资源加载,和网络端远程更新下载
1.命名文件夹下面的资源 assetBundleName
private static void RenameDirectorABName(string pFileDirectorRoot,string pSuffix = null)
{
string pFileDirectorPath = pFileDirectorRoot + "/";
if (Directory.Exists(pFileDirectorRoot))
{
var dirctory = new DirectoryInfo(pFileDirectorRoot);
var files = dirctory.GetFiles("*", SearchOption.AllDirectories);
for (var i = 0; i < files.Length; i++)
{
var file = files[i];
if (file.Name.EndsWith(".meta"))
continue;
if(pSuffix != null && !file.Name.EndsWith(pSuffix))
continue;
var fullName = file.FullName;
var fileName = file.Name;
var assetLength = Application.dataPath.Length - 6;
var assetPath = fullName.Substring(assetLength, fullName.Length - assetLength);
assetPath = assetPath.Replace('\\', '/');
var importer = AssetImporter.GetAtPath(assetPath);
var subName = fullName.Substring(pFileDirectorPath.Length, fullName.Length - pFileDirectorPath.Length);
subName = subName.Replace('\\', '/');
var lastIndex = subName.LastIndexOf('.');
subName = subName.Substring(0, lastIndex);
importer.assetBundleName = subName;
importer.assetBundleVariant = GameDefine.ABResourcesSuffix;
}
}
AssetDatabase.Refresh();
}
2. Lua 文件转txt文件
public static void CopyLuaFileToTextFile()
{
var textPath = GameSettings.GetLuaTextPath();
FileHelper.DeleteCreateNewDirectory(textPath);
var toLuaPath = GameSettings.GetToLuaResourcesPath();
FileHelper.CopyDirectoryAndSuffix(toLuaPath, textPath, ".lua", ".txt");
var luaPath = GameSettings.GetLuaResourcesPath();
FileHelper.CopyDirectoryAndSuffix(luaPath, textPath,".lua",".txt");
AssetDatabase.Refresh();
}
public static void CopyDirectoryAndSuffix(string srcDir, string tgtDir,string pSuffix,string pNewSuffix = null)
{
DirectoryInfo source = new DirectoryInfo(srcDir);
DirectoryInfo target = new DirectoryInfo(tgtDir);
if (target.FullName.StartsWith(source.FullName, StringComparison.CurrentCultureIgnoreCase))
{
throw new Exception("父目录不能拷贝到子目录!");
}
if (!source.Exists)
{
return;
}
if (!target.Exists)
{
target.Create();
}
FileInfo[] files = source.GetFiles();
for (int i = 0; i < files.Length; i++)
{
if (files[i].FullName.EndsWith(pSuffix))
{
string newFilePath = target.FullName + @"\" + files[i].Name;
if (pNewSuffix != null)
{
if (!newFilePath.EndsWith(pNewSuffix))
{
int lastIndex = newFilePath.LastIndexOf('.');
newFilePath = newFilePath.Substring(0, lastIndex);
newFilePath += pNewSuffix;
}
}
File.Copy(files[i].FullName, newFilePath, true);
}
}
DirectoryInfo[] dirs = source.GetDirectories();
for (int j = 0; j < dirs.Length; j++)
{
CopyDirectoryAndSuffix(dirs[j].FullName, target.FullName + @"\" + dirs[j].Name, pSuffix, pNewSuffix);
}
}
3.AB打包 这个5.0 中打包变的简单方便
private static void BuildAllABByTarget(BuildTarget pTarget)
{
var dirPath = GameSettings.GetABBuildDirectorPath();
FileHelper.DeleteCreateNewDirectory(dirPath);
BuildPipeline.BuildAssetBundles(dirPath, BuildAssetBundleOptions.DeterministicAssetBundle, pTarget);
AssetDatabase.Refresh();
}
4.记录所有文件的版本号`
public static void RecordProjectMd5Info(string pSavePath)
{
ResVersionRecorder md5Recorder = new ResVersionRecorder(pSavePath);
md5Recorder.ClearAllRecorder();
var dirPath = GameSettings.GetABBuildDirectorPath();
var dirctory = new DirectoryInfo(dirPath);
var files = dirctory.GetFiles("*", SearchOption.AllDirectories);
RecordProjectMd5Info(files, md5Recorder);
md5Recorder.RecoderTime = System.DateTime.Now.ToString();
md5Recorder.Save();
RecordTotalVersion();
}
5.更新流程 首次导入预载入资源
public override void OnRun()
{
if (GameSettings.IsSmallApo())
{
OnFinish();
}
bool editorNeedLoadRes = GameSettings.GetCurPlatform() == PlatformDefines.Editor &&
(GameSettings.ResLoadType == ResLoadType.LocalBuildAB || GameSettings.ResLoadType == ResLoadType.RemoteAB);
if (GameSettings.GetCurPlatform() == PlatformDefines.Android || editorNeedLoadRes)
{
var localTotalVersionPath = FileHelper.CombinePath(FileUtility.Util.GetPersistencePath(), GameDefine.LocalTotalVersion);
if (FileHelper.FileExist(localTotalVersionPath))
{
OnFinish();
return;
}
LoadDownLoadVersionRecorder();
LoadLocalVersionRecorder(()=> {
if (_localResVersionRecorder == null)
{
OnFinish();
return;
}
_NeedDownLoadResVersions = _localResVersionRecorder.GetDeltaResVersions(_downLoadVersionRecorder);
if (_NeedDownLoadResVersions == null || _NeedDownLoadResVersions.Count < 1)
{
OnAllResDownLoadFinish();
}
else
{
for (var i = 0; i < downLineCount; i++)
{
LoadAllPreRes();
}
}
});
}
else
{
OnFinish();
}
}
6.检查本地资源和远程资源版本 并确认更新大小
public override void OnRun()
{
if (GameSettings.GetCurPlatform() == PlatformDefines.Editor)
{
if (GameSettings.ResLoadType == ResLoadType.LocalRes || GameSettings.ResLoadType == ResLoadType.LocalAB)
{
OnFinish(0);
return;
}
}
LoadLocalVersionRecorder();
LoadRomateVersionRecorder(() => {
if (_lineResVersion != null)
{
_NeedDownLoadResVersions = _lineResVersion.GetDeltaResVersions(_localResVersion);
if (_NeedDownLoadResVersions == null || _NeedDownLoadResVersions.Count < 1)
{
OnFinish(0);
}
else
{
long fileSize = 0;
for (var i = 0; i < _NeedDownLoadResVersions.Count; i++)
{
fileSize += _NeedDownLoadResVersions[i].FileSize;
}
OnFinish(fileSize);
}
}
else
{
OnFinish(0);
}
});
}
7.更新远程资源
public override void OnRun()
{
if (GameSettings.GetCurPlatform() == PlatformDefines.Editor)
{
if (GameSettings.ResLoadType == ResLoadType.LocalRes || GameSettings.ResLoadType == ResLoadType.LocalAB || GameSettings.ResLoadType == ResLoadType.LocalBuildAB)
{
OnFinish();
return;
}
}
LoadLocalVersionRecorder();
LoadRomateVersionRecorder(() => {
if (_lineResVersion != null)
{
_NeedDownLoadResVersions = _lineResVersion.GetDeltaResVersions(_localResVersion);
if (_NeedDownLoadResVersions == null || _NeedDownLoadResVersions.Count < 1)
{
OnAllResDownLoadFinish();
}
else
{
for (var i = 0; i < downLineCount; i++)
{
LoadAllPreRes();
}
}
}
else
{
OnFinish();
}
});
}
8.最后是ab的资源加载和卸载
public UnityEngine.Object LoadResSynchByFilePath(string pResName)
{
string pResPath = GetABResLoadPath(pResName);
AssetBundle ab = AssetBundle.LoadFromFile(pResPath);
var lastIndex = pResName.LastIndexOf('/') + 1;
var resName = pResName.Substring(lastIndex, pResName.Length - lastIndex);
var resNameDe = pResName + "." + GameDefine.ABResourcesSuffix;
GetResDependenciesAndLoad(resNameDe);
var temp = ab.LoadAsset<GameObject>(resName);
ab.Unload(false);
return temp;
}
private string[] GetResDependenciesAndLoad(string pResName)
{
string[] strs = MainFest.GetAllDependencies(pResName);
if (strs.Length > 0)
{
for (var i = 0; i < strs.Length; i++)
{
AddABDependenciesRes(strs[i]);
GetResDependenciesAndLoad(strs[i]);
}
}
return strs;
}
private void AddABDependenciesRes(string pResPath)
{
if (!dependenciesCounts.ContainsKey(pResPath))
{
dependenciesCounts.Add(pResPath,0);
}
dependenciesCounts[pResPath] ++;
if (!dependenciesABs.ContainsKey(pResPath))
{
var resPath = GetABResPath(pResPath);
AssetBundle ab = AssetBundle.LoadFromFile(resPath);
dependenciesABs.Add(pResPath, ab);
}
}
public void UnloadResByFilePath(string pResName)
{
var resNameDe = pResName + "." + GameDefine.ABResourcesSuffix;
GetResDependenciesAndUnload(resNameDe);
}
第一次写ab 方面的问题,还有很多地方有待提高,希望大家多多指点!