Unity一键发版脚本折腾记(Windows版)

脚本起源

策划:煎饼啊,给我一个最新的电脑版~
煎饼:好~

于是,开始手动发版,操作步骤如下:

  • 运行Unity,把平台切换到Windows
  • 去到项目代码文件夹里边,先还原代码,再拉取最新代码
  • 手动把测试模块拖动到主场景的Main Camera上
  • 在工具面板点击打包资源按钮(开发提供)
  • 在工具面板点击发版按钮(开发提供)

偶尔会忘记拉取最新代码,偶尔会忘记打包资源,最重要的是,这发版步骤还是略繁琐,于是懒人症发作,开始探索如何脚本化这个过程。

探索过程

这些步骤分为两类操作。

一类是Unity外的操作,如还原,拉取代码,这个可以用Python解决。

一类是Unity内的操作,切换平台,打包资源,进行发版。这些操作,外部工具不好直接介入,最好的方式是Unity提供了命令行的操作形式,搜索了下,果然是有,研究了下,找到了几个可用的参数。

1
2
3
4
-batchmode 在批处理模式下运行,不会弹出Unity窗口
-quit 其他命令执行完毕后将退出Unity编辑器
-logFile <pathname> 指定输出Log文件
-executeMethod <ClassName.MethodName> 在Unity启动的同时会执行指定的静态方法,注意,这个类所在文件目录,需要在Editor目录下(自己建一个Editor目录也行)

最终调用命令如下:

Unity.exe -quit -batchmode -executeMethod CMDTool.BuildWindows -logFile C:\build\log.log

更多参数点击查看官方文档

实现过程

Unity发版的工具类

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
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using Assets.Src.Editor.Toolkit.Tools;
public class CMDTool {
public static void BuildWindows() {
SwitchPlatform(BuildTarget.StandaloneWindows);
CheckTestManager();
SGTools.BuildAssetBundles(EditorUserBuildSettings.activeBuildTarget, true);
SGTools.Build(EditorUserBuildSettings.activeBuildTarget);
}
public static void SwitchPlatform(BuildTarget target) {
if (EditorUserBuildSettings.activeBuildTarget != target) {
EditorUserBuildSettings.SwitchActiveBuildTarget(target);
}
}
public static void CheckTestManager() {
EditorSceneManager.OpenScene("Assets/Scene/Main.unity");
if (GameObject.Find("Main Camera").GetComponent<TestCenter.TestManager>().IsNull()) {
GameObject.Find("Main Camera").AddComponent<TestCenter.TestManager>();
}
}
}

SwitchPlatform 切换平台
CheckTestManager 加载测试模块
SGTools.BuildAssetBundles 开发提供的打包资源方法
SGTools.Build 开发提供的发版方法

还原,拉取项目代码

为什么要还原?因为每次发版都会注入测试模块,下次发版前拉取新代码的时候,会出现冲突。

可以使用Python来调用Git命令:

1
2
3
4
5
6
def update_unity_code():
os.chdir("C:\Project\sg")
print 'start to reset'
os.system("git reset --hard HEAD")
print 'start to pull'
os.system("git pull")

检查Unity是否已经关闭

调用Unity命令行发版之前,需要确认Unity没有开启,否则运行会报错。

1
2
3
4
5
6
7
def check_unity_is_close():
import psutil
for i in psutil.process_iter():
if i.name() == "Unity.exe":
raise Exception("unity is not close")
else:
print "unity is close"

检查发版的Log文件,是否有报错信息

1
2
3
4
5
6
def analyze_log():
print 'start to analyze log'
with open(r"C:\build\log.log") as f:
for i in f:
if i.find("error") > -1:
print i

发版函数

1
2
3
4
5
6
7
8
def build_windows():
print 'start to build windows'
os.chdir(r"C:\Program Files\Unity\Editor")
p = subprocess.Popen(r"Unity.exe -quit -batchmode -executeMethod CMDTool.BuildWindows -logFile C:\build\log.log", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
print stdout
print stderr
print "result code is {}".format(p.returncode)

最终运行

1
2
3
4
5
6
7
if __name__ == '__main__':
start_time = time.time()
check_unity_is_close()
update_unity_code()
build_windows()
analyze_log()
print 'finish in {} seconds.'.format(time.time() - start_time)