因为之前在接平台SDK的时候,为了后期打包方便,写了个一键打包工具,后面平台说要做融合SDK,那就意味着需要给游戏aar包,突然发现白写了。很伤心,就共享出来。只写了安卓的一键打包,IOS的也是刚碰的,虽然IOS的SDK接好了,但也没超过10天,所以还没去弄。估计后面也不会去弄了。
先来个简短的
public static class AutoBuilder
{
private const string startScenePath = "Assets/Resources/Scene/Main.unity";
public static string[] GetScenePaths()
{
int count = 0;
string[] scenes = new string[count];
return scenes;
}
public static void CopyPlatformInfo(string platformSDKPath)
{
if (string.IsNullOrEmpty(platformSDKPath)) return;
if(EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
{
if (Directory.Exists(AssetHelper.AndroidPluginsPath))
Directory.Delete(AssetHelper.AndroidPluginsPath, true);
if (Directory.Exists(platformSDKPath))
ToolsWindow.CopyDirectory(platformSDKPath, AssetHelper.PluginsPath);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
public static void AutoBuildApp(string publisPath)
{
if(EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
{
BuildPipeline.BuildPlayer(GetScenePaths(), publisPath, BuildTarget.Android, BuildOptions.None);
}
}
}
CopyPlatformInfo方法的主要功能就是拷贝不同平台的配置文件,为了方便,我是把当前Unity工程下的Plugins中的Android整个目录删除,再从配置好的SDK目录下拷贝到Unity工程下的Plugins中,就是这么简单,不要忘了调用AssetDatabase.SaveAssets()和AssetDatabase.Refresh()这两个接口。
AutoBuildApp方法就不用解释了,就官方的打包接口。
接下来的就是一个窗口类
public class PlatformInfo
{
public string PlatformId;
public string PlatformName;
public string PlatformPath;
public string PlatformBuildNameExt;
}
public static class AssetHelper
{
public static string RootPath = Application.dataPath.Substring(0, Application.dataPath.Length - ("Assets".ToString().Length));
public static string PluginsPath = Application.dataPath + "/Plugins";
public static string AndroidPluginsPath = Application.dataPath + "/Plugins/Android";
public static string BuildPath = RootPath + "/Builds/";
public static string[] NeedDeletePath = { Application.dataPath + "/Plugins/x86" };
}
public class ToolsWindow : EditorWindow
{
private bool bIsInit = false;
public Dictionary<string, PlatformInfo> pInfoList = new Dictionary<string, PlatformInfo>();
public Dictionary<string, bool> packSelectList = new Dictionary<string, bool>();
private bool bIsShowLog = false;
[MenuItem("Tools/打包工具")]
static void Open()
{
GetWindow<ToolsWindow>("打包工具");
}
#region 方法
public static List<string> ReadFileByLine(string filePath)
{
List<string> infoList = new List<string>();
if (!File.Exists(filePath))
return infoList;
FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
StreamReader streamReader = new StreamReader(fileStream);
do
{
string lineStr = streamReader.ReadLine();
if (lineStr == null || lineStr.Length == 0)
break;
if (!lineStr.Contains("#"))
infoList.Add(lineStr);
}
while (true);
fileStream.Close();
streamReader.Close();
return infoList;
}
/// <summary>
/// 拷贝文件夹
/// </summary>
/// <param name="sourceDirectory"></param>
/// <param name="destDirectory"></param>
public static void CopyDirectory(string sourceDirectory, string destDirectory)
{
if (string.IsNullOrEmpty(sourceDirectory) || string.IsNullOrEmpty(destDirectory)) return;
var sourceFilesPath = Directory.GetFileSystemEntries(sourceDirectory);
for (int i = 0; i < sourceFilesPath.Length; ++i)
{
var sourceFilePath = sourceFilesPath[i];
sourceFilePath = sourceFilePath.Replace("\\","/");
var directoryName = Path.GetDirectoryName(sourceFilePath);
var folders = directoryName.Split('/');
var lastDirectory = folders[folders.Length - 1];
var dest = destDirectory + "/" + lastDirectory;
//Debug.LogError(directoryName + "----" + dest);
if (File.Exists(sourceFilePath))
{
var sourceFileName = Path.GetFileName(sourceFilePath);
if (!Directory.Exists(dest))
{
Directory.CreateDirectory(dest);
}
//Debug.LogError(sourceFilePath + "----" + dest + sourceFileName);
File.Copy(sourceFilePath, dest + "/" + sourceFileName, true);
}
else
CopyDirectory(sourceFilePath, dest);
}
}
public static string GetPublishPath(string PlatformBuildNameExt)
{
string publishPath = AssetHelper.BuildPath;
if (!Directory.Exists(publishPath))
Directory.CreateDirectory(publishPath);
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
{
publishPath += "Android/";
}
if (!Directory.Exists(publishPath))
Directory.CreateDirectory(publishPath);
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
{
string timeExt = System.DateTime.Now.ToString("yyyyMMddHHmm");
publishPath += "game" + "_" + PlatformBuildNameExt + "_" + timeExt + ".apk";
}
return publishPath;
}
#endregion
void Init()
{
pInfoList.Clear();
List<string> pInfoStrList = ReadFileByLine(AssetHelper.RootPath + "sdkconfig/PlatformInfo.txt");
foreach(string pInfoStr in pInfoStrList)
{
int index = 0;
string[] infoStr = pInfoStr.Split('|');
if(infoStr != null)
{
PlatformInfo temp = new PlatformInfo();
int length = infoStr.Length;
if(length > index)
{
temp.PlatformId = infoStr[index];
++index;
}
if (length > index)
{
temp.PlatformName = infoStr[index];
++index;
}
if (length > index)
{
temp.PlatformPath = infoStr[index];
++index;
}
if (length > index)
{
temp.PlatformBuildNameExt = infoStr[index];
++index;
}
pInfoList.Add(temp.PlatformId, temp);
}
}
bIsInit = true;
}
/// <summary>
/// 开启日志
/// </summary>
/// <param name="bIsShow"></param>
void SetLogging(bool bIsShow)
{
if(bIsShow)
{
PlayerSettings.SetStackTraceLogType(LogType.Assert, StackTraceLogType.Full);
PlayerSettings.SetStackTraceLogType(LogType.Error, StackTraceLogType.Full);
PlayerSettings.SetStackTraceLogType(LogType.Exception, StackTraceLogType.Full);
PlayerSettings.SetStackTraceLogType(LogType.Log, StackTraceLogType.Full);
PlayerSettings.SetStackTraceLogType(LogType.Warning, StackTraceLogType.Full);
}
else
{
PlayerSettings.SetStackTraceLogType(LogType.Assert, StackTraceLogType.None);
PlayerSettings.SetStackTraceLogType(LogType.Error, StackTraceLogType.None);
PlayerSettings.SetStackTraceLogType(LogType.Exception, StackTraceLogType.None);
PlayerSettings.SetStackTraceLogType(LogType.Log, StackTraceLogType.None);
PlayerSettings.SetStackTraceLogType(LogType.Warning, StackTraceLogType.None);
}
}
void OnGUI()
{
if (!bIsInit || pInfoList.Count <= 0)
Init();
GUILayout.Label("平台选择(勾选的打包)");
EditorGUILayout.BeginHorizontal();
int index = 0;
foreach (var pi in pInfoList)
{
if (pi.Value == null) continue;
GUILayout.Label(pi.Value.PlatformName + ":" + pi.Value.PlatformId);
bool bIsSelect = false;
packSelectList.TryGetValue(pi.Value.PlatformId, out bIsSelect);
bool check = EditorGUILayout.Toggle(bIsSelect);
if (check != bIsSelect)
packSelectList[pi.Value.PlatformId] = check;
if((index + 1) % 4 == 0)
{
GUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
}
++index;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
bool bIsShow = bIsShowLog;
bool bCheck = EditorGUILayout.Toggle("是否显示日志", bIsShow);
if (bCheck != bIsShow)
bIsShowLog = bCheck;
SetLogging(bIsShowLog);
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("发包"))
{
Config.useLuaAB = true;
SDKManager.bIsTest = true;
if (AssetHelper.NeedDeletePath.Length > 0)
{
foreach (var path in AssetHelper.NeedDeletePath)
{
if (Directory.Exists(path))
Directory.Delete(path, true);
}
}
if (packSelectList.Count <= 0)
{
Debug.LogError("请勾选需要发布的平台");
}
else
{
foreach (var selectInfo in packSelectList)
{
if (selectInfo.Value == false || !pInfoList.ContainsKey(selectInfo.Key)) continue;
PlatformInfo temp = pInfoList[selectInfo.Key];
if (temp == null || string.IsNullOrEmpty(temp.PlatformPath)) continue;
AutoBuilder.CopyPlatformInfo(AssetHelper.RootPath + temp.PlatformPath);
AutoBuilder.AutoBuildApp(GetPublishPath(temp.PlatformBuildNameExt));
}
}
}
}
}
有注释的就不多介绍了,代码很简单。
PlatformInfo和AssetHelper这两个类就不用解释,一个存储平台信息,一个则是安卓插件目录,需要删除的文件夹等。
ReadFileByLine函数的功能就是读取存储平台信息的txt文件。
GetPublishPath函数的功能就是生成apk目录。
Init函数的功能就是存储平台信息。方便后面选择要打什么包。
OnGUI都有文字介绍,也蛮清晰的,就不多说了。