Unity编辑器提供了手动打包的功能,但还是很麻烦。每次策划人员需要游戏包了,都要过来找程序员打包。为了方便,可以考虑让策划人员来打包,或者每天凌晨自动打包。但是打包也不是那么容易的,通常需要在打包前后自动执行一些特殊代码,例如Logo、图标、编译选项、复制和第三方库的依赖等。

打包前后事件

打包时,我们需要监听一些事件,比如打包前设置版本号、游戏名和图标等,打包后可能需要复制或者压缩游戏包等

我们可以监听打包前和打包后的事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;

public class ListeningBuildingEvents : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
int IOrderedCallback.callbackOrder{
get{
return 0;//返回回调的相对回调顺序。具有较低值的回调在具有较高值的​​回调之前被调用。
}
}
//打包前事件
void IPreprocessBuildWithReport.OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report){
//设置版本号和游戏名
PlayerSettings.bundleVersion = "0.0.1";
PlayerSettings.productName = "ATAO2017";
}
//打包后事件
void IPostprocessBuildWithReport.OnPostprocessBuild(UnityEditor.Build.Reporting.BuildReport report){
Debug.LogFormat("游戏包生成路径:{0}",report.summary.outputPath);
}
}

本节所有的Shell脚本都无法生效

windows使用Shell的方法待补充

或许大部分使用Python代替

打包后自动压缩

使用Shell脚本,将游戏打包后自动压缩成一个zip文件。

Shell 教程 | 菜鸟教程 (runoob.com),可以使用GIT Bash来运行shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using UnityEditor.Build;
using System.IO;

public class AutoCompressAfterBuild : IPreprocessBuildWithReport,IPostprocessBuildWithReport
{
int IOrderedCallback.callbackOrder{
get{
return 0;//返回回调的相对回调顺序。具有较低值的回调在具有较高值的​​回调之前被调用。
}
}
//打包前事件
void IPreprocessBuildWithReport.OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report){
//清空上次打包的残留
string data = Path.Combine(Path.GetDirectoryName(report.summary.outputPath),Path.GetFileNameWithoutExtension(report.summary.outputPath)+"_Data");

if(File.Exists(report.summary.outputPath))
File.Delete(report.summary.outputPath);
if(File.Exists(data))
File.Delete(data);
}
//打包后事件
void IPostprocessBuildWithReport.OnPostprocessBuild(UnityEditor.Build.Reporting.BuildReport report){
string data = Path.Combine(Path.GetDirectoryName(report.summary.outputPath),Path.GetFileNameWithoutExtension(report.summary.outputPath)+"_Data");
string zip = Path.Combine(Path.GetDirectoryName(report.summary.outputPath),"project.zip");

//清空上次打包的zip文件
if(File.Exists(zip))
File.Delete(zip);

//压缩资源包
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = "C:\\Program Files\\Git\\git-bash.exe";
process.StartInfo.Arguments = string.Format("-e 'tell application \"Windows PowerShell\" to do script \"zip -r {0} {1} {2}\"'",zip,report.summary.outputPath,data);
process.Start();
process.WaitForExit();
process.Close();

}
}

此代码仅作演示,在Windows平台下并不会运行,需要配置windows终端(Power Shell)的zip命令

用C#调用Shell脚本

创建下面的shell脚本,这个脚本的含义是复制文件

1
2
3
4
5
6
7
#!/bin/sh

from=$1
to=$2

#复制文件
cp -vf "${from}" "${to}"

在C#中调用此脚本,并且将参数传递给它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using UnityEngine;
using UnityEditor;
using System.IO;

public class CopyPrefabByShell
{
[MenuItem("Tool/CopyShell")]
static void CopyShell()
{
string shell = Path.Combine(Application.dataPath, "copy.sh");
string arg1 = Path.Combine(Application.dataPath, "Sphere.prefab");
string arg2 = Path.Combine(Application.dataPath, "Sphere1.prefab");
string args = shell + " " + arg1 + " " + arg2;

System.Diagnostics.Process.Start("C:\\Program Files\\Git\\git-bash.exe", args);
}
}

等待Shell结束

有时候,我们需要通过shell脚本执行一些压缩命令。由于它不能在一帧内完成,所以需要等待shell脚本执行完后再执行后面的代码。

首先,在shell脚本里面模拟一个耗时操作

1
2
3
4
5
6
7
8
#!/bin/sh

count=$1

#耗时操作
for((i=1;i<=$count;i++));do
echo $(expr $i \* 4);
done

接着在C#中传入count = 10000来阻塞主线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using UnityEngine;
using UnityEditor;
using System.IO;
using System;

public class WaitingForShell
{
[MenuItem("Tool/Waiting")]
static void WaitingShell()
{
string shell = Path.Combine(Application.dataPath, "copy.sh");
int arg1 = 10000;
string args = shell + " " + arg1;
Debug.LogFormat("begin : {0}", DateTime.Now.ToString("hh:mm:ss").ToString());
System.Diagnostics.Process.Start("C:\\Program Files\\Git\\git - bash.exe", args).WaitForExit();
Debug.LogFormat("end : {0}", DateTime.Now.ToString("hh:mm:ss").ToString());
}
}

Shell脚本调用C#

Shell脚本自动打包

公共打包机配置jenkins服务