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");
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服务