484 lines
18 KiB
C#
484 lines
18 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
using System.IO;
|
||
using ResMgr;
|
||
using GameEditor.AssetBundle;
|
||
using GameEditor.Core;
|
||
using GameCore;
|
||
using ResUpdate;
|
||
using GameLogic;
|
||
|
||
namespace GameEditor.FrameTool
|
||
{
|
||
public class FrameTool
|
||
{
|
||
|
||
/// <summary>
|
||
/// 初始化游戏环境
|
||
/// </summary>
|
||
//[MenuItem("GameFrame/InitResEnvironment", false, 1)]
|
||
//public static void InitResEnvironment()
|
||
//{
|
||
// ResourcesPathEditor.InitIgnoreList();
|
||
//}
|
||
|
||
/// <summary>
|
||
/// 刷新资源配置文件
|
||
/// </summary>
|
||
[MenuItem("GameFrame/刷新资源配置", false, 2)]
|
||
public static void RefreshResPathConfigs()
|
||
{
|
||
ResourcesPathEditor.CreateResourcePathConfig();
|
||
EditorUtil.ShowSureDialog("资源配置文件生成完毕!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查资源循环依赖
|
||
/// </summary>
|
||
[MenuItem("GameFrame/检查循环依赖", false, 2)]
|
||
public static void CheckDependences()
|
||
{
|
||
ResourcesPathEditor.ForEachCheckDependences();
|
||
EditorUtil.ShowSureDialog("检查完毕!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 战斗服务端验证同步
|
||
/// </summary>
|
||
[MenuItem("GameFrame/战斗逻辑同步", false, 2)]
|
||
public static void BattleLogicSync()
|
||
{
|
||
string p = Application.dataPath;
|
||
p = p.Substring(0, p.LastIndexOf('/'));
|
||
string t1 = p.Substring(p.LastIndexOf('/'), p.Length - p.LastIndexOf('/'));
|
||
p = p.Substring(0, p.LastIndexOf('/'));
|
||
string t2 = p.Substring(p.LastIndexOf('/'), p.Length - p.LastIndexOf('/'));
|
||
p = p.Substring(0, p.LastIndexOf('/'));
|
||
string p2 = p + "/battleWeb" + t2 + t1;
|
||
|
||
string[] files = Directory.GetFiles(AppConst.GameResRealPath + "/~Lua/Modules/Battle/Logic", "*.lua", SearchOption.AllDirectories);
|
||
foreach (var s in files)
|
||
{
|
||
string s2 = s.Replace(Application.dataPath + "/ManagedResources/~Lua", p2);
|
||
FileUtils.CopyFile(s, s2);
|
||
}
|
||
Debug.LogError("同步完成!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有游戏
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public static string[] GetAllGames() {
|
||
string fullPath = EditorUtil.GetFullPath(AppConst.GameResPath);
|
||
string[] directorys = Directory.GetDirectories(fullPath);
|
||
string[] games = new string[directorys.Length];
|
||
string game = string.Empty;
|
||
for (int i = 0; i < directorys.Length; i++)
|
||
{
|
||
game = Path.GetFileName(directorys[i]);
|
||
games[i] = game;
|
||
}
|
||
return games;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新选中资源配置文件
|
||
/// </summary>
|
||
[MenuItem("Assets/GameFrame/RefreshResPathConfig")]
|
||
public static void RefreshResPathConfig()
|
||
{
|
||
try
|
||
{
|
||
ResourcesPathEditor.CreateResourcePathConfig();
|
||
EditorUtil.ShowSureDialog("资源配置文件生成完毕!");
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogErrorFormat("RefreshResPathConfigError:{0}", e.ToString());
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 整体打包
|
||
/// </summary>
|
||
public static void BuildAll()
|
||
{
|
||
AssetBundleBuilder.ClearMarks();
|
||
BuildGameAssetBundles();
|
||
}
|
||
|
||
|
||
[MenuItem("AssetBundle/MarkAllGame")]
|
||
/// <summary>
|
||
/// 标记所有游戏
|
||
/// </summary>
|
||
public static void MarkAllGame()
|
||
{
|
||
MarkGame(false);
|
||
ResourcesPathEditor.CreateResourcePathConfig();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 检查AB包的资源合法性
|
||
/// 1.AssetBundle的循环依赖
|
||
/// 2.AssetBundle的跨游戏依赖
|
||
/// </summary>
|
||
public static void CheckAssetBundleStates() {
|
||
AssetBundleBuilder.ClearMarks();
|
||
MarkAllGame();
|
||
}
|
||
|
||
public static void AssetsDuplicatedInMultBundlesCache(int type)
|
||
{
|
||
string target;
|
||
foreach(var path in AssetBundleBrowser.AssetBundleModel.Model.AssetsDuplicatedInMultBundlesCache)
|
||
{
|
||
if(type == 1)
|
||
{
|
||
Debug.LogError("path:" + path);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("正在移动:" + path);
|
||
string extension = Path.GetExtension(path).ToLower();
|
||
switch (extension)
|
||
{
|
||
case ".png":
|
||
case ".tga":
|
||
target = "Textures/";
|
||
break;
|
||
case ".mat":
|
||
target = "Materials/";
|
||
break;
|
||
case ".fbx":
|
||
target = "Models/";
|
||
break;
|
||
case ".anim":
|
||
case ".controller":
|
||
target = "Animations/";
|
||
break;
|
||
default:
|
||
target = null;
|
||
break;
|
||
}
|
||
if (target != null)
|
||
{
|
||
File.Move(Application.dataPath + path.Replace("Assets", ""),
|
||
AppConst.GameResRealPath + "/PublicArtRes/" + target + Path.GetFileNameWithoutExtension(path) + extension);
|
||
File.Move(Application.dataPath + path.Replace("Assets", "") + ".meta",
|
||
AppConst.GameResRealPath + "/PublicArtRes/" + target + Path.GetFileNameWithoutExtension(path) + extension + ".meta");
|
||
}
|
||
}
|
||
}
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打包游戏
|
||
/// </summary>
|
||
public static void BuildGameAssetBundles()
|
||
{
|
||
AssetBundleBuilder.ClearMarks();
|
||
MarkGame(true);
|
||
string exportPath = AssetBundleConfig.GetExportPath(EditorUserBuildSettings.activeBuildTarget);
|
||
if (Directory.Exists(exportPath))
|
||
Directory.Delete(exportPath, true);
|
||
AssetBundleBuilder.BuildAssetBundleWithType(exportPath, AssetBundleConfig.LZ4Options, EditorUserBuildSettings.activeBuildTarget, CompressType.LZ4);
|
||
AssetBundleBuilder.BuildAssetBundleWithType(exportPath, AssetBundleConfig.LZMAOptions, EditorUserBuildSettings.activeBuildTarget, CompressType.LZMA);
|
||
CreateCRCFiles(exportPath);
|
||
AssetBundleBuilder.ClearManifest(exportPath);
|
||
EditorUtil.OpenFolderAndSelectFile(exportPath);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 拷贝AssetBundle到StreamingAssets
|
||
/// </summary>
|
||
/// <param name="games"></param>
|
||
public static void CopyAssetBundleToStreamingAssets()
|
||
{
|
||
string exportPath = AssetBundleConfig.GetExportPath(EditorUserBuildSettings.activeBuildTarget);
|
||
string streamingPath = GetStreamingAssetPath(EditorUserBuildSettings.activeBuildTarget);
|
||
//Debug.LogError(streamingPath);
|
||
if (Directory.Exists(streamingPath)) Directory.Delete(streamingPath,true);
|
||
Directory.CreateDirectory(streamingPath);
|
||
FileUtils.CopyDir(exportPath, streamingPath);
|
||
//CopyResourceFiles();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 单打lua资源
|
||
/// </summary>
|
||
public static bool BuildLuaAssetBundles()
|
||
{
|
||
AssetImporter ai = AssetImporter.GetAtPath(AppConst.GameResPath + "/LuaBytes");
|
||
if(ai == null)
|
||
{
|
||
Debug.LogError("lua资源不存在!请先打全包!");
|
||
return false;
|
||
}
|
||
|
||
AssetBundleBuilder.ClearMarks();
|
||
MarkGame(true);
|
||
|
||
AssetBundleBuild build = new AssetBundleBuild();
|
||
build.assetBundleName = ai.assetBundleName;
|
||
build.assetBundleVariant = ai.assetBundleVariant;
|
||
build.assetNames = new string[] { ai.assetPath };
|
||
|
||
AssetImporter ai2 = AssetImporter.GetAtPath(AppConst.GameResPath + "/ResConfigs");
|
||
AssetBundleBuild build2 = new AssetBundleBuild();
|
||
build2.assetBundleName = ai2.assetBundleName;
|
||
build2.assetBundleVariant = ai2.assetBundleVariant;
|
||
build2.assetNames = new string[] { ai2.assetPath };
|
||
|
||
string exportPath = AssetBundleConfig.GetExportPath(EditorUserBuildSettings.activeBuildTarget);
|
||
var manifest = BuildPipeline.BuildAssetBundles(exportPath, new AssetBundleBuild[] { build, build2 }, BuildAssetBundleOptions.DeterministicAssetBundle, EditorUserBuildSettings.activeBuildTarget);
|
||
|
||
// 加密 文件前加入128个空字符
|
||
foreach (var name in manifest.GetAllAssetBundles())
|
||
{
|
||
var uniqueSalt = Encoding.UTF8.GetBytes(name);
|
||
string pn = Path.Combine(exportPath, name);
|
||
byte[] oldData = File.ReadAllBytes(pn);
|
||
int len = (int)GameLogic.AppConst.EncyptBytesLength;
|
||
int newOldLen = len + oldData.Length;//定死了,128个空byte
|
||
var newData = new byte[newOldLen];
|
||
for (int tb = 0; tb < oldData.Length; tb++)
|
||
{
|
||
newData[len + tb] = oldData[tb];
|
||
}
|
||
FileStream fs = File.OpenWrite(pn);//打开写入进去
|
||
fs.Write(newData, 0, newOldLen);
|
||
fs.Close();
|
||
}
|
||
|
||
|
||
CreateCRCFiles(exportPath);
|
||
AssetBundleBuilder.ClearManifest(exportPath);
|
||
AssetDatabase.Refresh();
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 数据目录
|
||
/// </summary>
|
||
static string AppDataPath
|
||
{
|
||
get { return Application.dataPath.ToLower(); }
|
||
}
|
||
|
||
public static void CopyResourceFiles()
|
||
{
|
||
string AssetRoot = "StreamingAssets/Android";
|
||
if (BuildTarget.iOS == EditorUserBuildSettings.activeBuildTarget)
|
||
{
|
||
AssetRoot = "StreamingAssets/IOS";
|
||
}
|
||
string ResourcePath = "Resources/";
|
||
string resPath = AppDataPath + "/" + AssetRoot + "/";
|
||
///----------------------创建文件列表-----------------------
|
||
string newFilePath = resPath + "/" + ResourcePath;
|
||
if (Directory.Exists(newFilePath))
|
||
Directory.Delete(newFilePath, true);
|
||
|
||
Directory.CreateDirectory(newFilePath);
|
||
string sourcePath = Application.dataPath + "/Resources/";
|
||
string[] files = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories);
|
||
|
||
foreach (var file in files)
|
||
{
|
||
FileInfo info = new FileInfo(file);
|
||
File.Copy(file, newFilePath + info.Name, true);
|
||
}
|
||
}
|
||
|
||
public static void SaveVersionFile()
|
||
{
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建CRC文件
|
||
/// </summary>
|
||
/// <param name="exportPath"></param>
|
||
public static void CreateCRCFiles(string exportPath)
|
||
{
|
||
string fullPath = exportPath;
|
||
if (!Directory.Exists(fullPath))
|
||
return;
|
||
string[] files = Directory.GetFiles(fullPath, "*.unity3d", SearchOption.AllDirectories);
|
||
string savePath = string.Format("{0}/CRC/game.asset", Application.dataPath);
|
||
string saveAssetPath = EditorUtil.GetAssetsPath(savePath);
|
||
ResourceFiles resourceFiles = null;
|
||
if (File.Exists(savePath))
|
||
{
|
||
resourceFiles = AssetDatabase.LoadAssetAtPath<ResourceFiles>(saveAssetPath);
|
||
}
|
||
else
|
||
{
|
||
string directory = Path.GetDirectoryName(savePath);
|
||
if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
|
||
resourceFiles = ScriptableObject.CreateInstance<ResourceFiles>();
|
||
AssetDatabase.CreateAsset(resourceFiles,saveAssetPath);
|
||
}
|
||
if (resourceFiles == null)
|
||
{
|
||
string message = string.Format("资源CRC信息列表文件{0}错误,请查看", savePath);
|
||
EditorUtility.DisplayDialog("提示", message, "确定");
|
||
return;
|
||
}
|
||
if(resourceFiles.files==null)
|
||
resourceFiles.files = new List<ResourceFile>();
|
||
resourceFiles.files.Clear();
|
||
FileInfo info = null;
|
||
ResourceFile file = null;
|
||
for (int i = 0; i < files.Length; i++)
|
||
{
|
||
files[i] = EditorUtil.FixedWindowsPath(files[i]);
|
||
info = new FileInfo(files[i]);
|
||
file = new ResourceFile();
|
||
file.id = i + 1;
|
||
file.fileName = files[i].Replace(exportPath+"/",string.Empty);
|
||
file.size = info.Length;
|
||
file.crc = FileToCRC32.GetFileCRC32(files[i]);
|
||
resourceFiles.files.Add(file);
|
||
}
|
||
EditorUtility.SetDirty(resourceFiles);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
|
||
AssetBundleBuilder.BuildAssetBundle(resourceFiles, "files", exportPath, AssetBundleConfig.LZMAOptions, EditorUserBuildSettings.activeBuildTarget);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 拷贝Lua文件
|
||
/// </summary>
|
||
public static void CopyLuaFiles() {
|
||
try
|
||
{
|
||
string luaBytesFullPath = EditorUtil.GetFullPath(string.Format("{0}/LuaBytes", AppConst.GameResPath));
|
||
if (!Directory.Exists(luaBytesFullPath))
|
||
{
|
||
Directory.CreateDirectory(luaBytesFullPath);
|
||
}
|
||
List<string> files = EditorUtil.GetFiles(luaBytesFullPath, "*", SearchOption.AllDirectories);
|
||
for (int i = 0; i < files.Count; i++) {
|
||
File.Delete(files[i]);
|
||
}
|
||
string luaFullPath = EditorUtil.GetFullPath(string.Format("{0}/~Lua", AppConst.GameResPath));
|
||
files = EditorUtil.GetFiles(luaFullPath, "*.lua", SearchOption.AllDirectories);
|
||
string inPath = string.Empty;
|
||
string outPath = string.Empty;
|
||
for (int i = 0; i < files.Count; i++) {
|
||
inPath = files[i];
|
||
outPath = inPath.Replace(luaFullPath+"/", string.Empty).Replace("/","%").Replace(".lua",".bytes");
|
||
outPath = luaBytesFullPath + "/" + outPath;
|
||
//FileUtils.CopyFile(inPath, outPath);
|
||
Packager.EncodeLuaFile(inPath, outPath);
|
||
}
|
||
Debug.LogFormat("拷贝Lua文件完成!");
|
||
AssetDatabase.Refresh();
|
||
}
|
||
catch (Exception e) {
|
||
Debug.LogErrorFormat("CopyLuaFiles error:{0}",e);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理lua文件
|
||
/// </summary>
|
||
/// <param name="inpath"></param>
|
||
/// <param name="outPath"></param>
|
||
public static void HandleLuaFile(string inpath, string outPath) {
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 标记一个游戏
|
||
/// </summary>
|
||
public static void MarkGame(bool refreshConfig = false)
|
||
{
|
||
try
|
||
{
|
||
//拷贝Lua文件
|
||
CopyLuaFiles();
|
||
//标记Lua
|
||
string buildConfigPath = string.Format("{0}/EditorConfigs/BuildConfigs.asset", AppConst.GameResPath);
|
||
AssetBundleBuildConfigs configs = AssetDatabase.LoadAssetAtPath<AssetBundleBuildConfigs>(buildConfigPath);
|
||
AssetBundleBuildConfig[] paths = configs.OneFloderOneBundle;
|
||
for (int i = 0; i < paths.Length; i++)
|
||
{
|
||
if (string.IsNullOrEmpty(paths[i].Path))
|
||
{
|
||
Debug.LogErrorFormat("MarkGame error:BuildConfigs contain null floder." + paths[i].Path);
|
||
continue;
|
||
}
|
||
AssetBundleBuilder.MarkOneFloderOneBundle(paths[i].Path, paths[i].CompressType);
|
||
}
|
||
paths = configs.SubFloderOneBundle;
|
||
for (int i = 0; i < paths.Length; i++)
|
||
{
|
||
if (string.IsNullOrEmpty(paths[i].Path))
|
||
{
|
||
Debug.LogErrorFormat("MarkGame error:BuildConfigs contain null floder.");
|
||
continue;
|
||
}
|
||
AssetBundleBuilder.MarkSubFloderOneBundle(paths[i].Path,paths[i].CompressType);
|
||
}
|
||
|
||
paths = configs.OneAssetOneBundle;
|
||
for (int i = 0; i < paths.Length; i++)
|
||
{
|
||
if (string.IsNullOrEmpty(paths[i].Path))
|
||
{
|
||
Debug.LogErrorFormat("MarkGame error:BuildConfigs contain null floder");
|
||
continue;
|
||
}
|
||
AssetBundleBuilder.MarkOneAssetOneBundle(paths[i].Path, true, paths[i].CompressType);
|
||
}
|
||
if (refreshConfig)ResourcesPathEditor.CreateResourcePathConfig();
|
||
Debug.LogFormat("标记游戏完成!");
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogErrorFormat("MarkGameError:{0}", e);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取流媒体目录
|
||
/// </summary>
|
||
/// <param name="target"></param>
|
||
/// <returns></returns>
|
||
public static string GetStreamingAssetPath(BuildTarget target) {
|
||
string floder = "Other";
|
||
switch (target)
|
||
{
|
||
case BuildTarget.Android:
|
||
floder = "Android";
|
||
break;
|
||
case BuildTarget.iOS:
|
||
floder = "IOS";
|
||
break;
|
||
case BuildTarget.StandaloneWindows:
|
||
floder = "Windows";
|
||
break;
|
||
case BuildTarget.StandaloneWindows64:
|
||
floder = "Windows";
|
||
break;
|
||
}
|
||
return Application.streamingAssetsPath + "/" + floder;
|
||
}
|
||
|
||
}
|
||
}
|