基于python脚本,实现Unity全平台的自动打包
转载请标明出处:http://www.cnblogs.com/zblade/
0. 概述
本文主要针对项目中自动打包过程进行调研,实现用python脚本来打出win/android/ios三个平台下的游戏运行包。
1.工具安装
首先基本的工具需要安装,Unity, python, 如果需要修改python脚本,则需要安装一下pycharm,对应的链接:
用最新版本即可
选中最新的即可
pyCharm最新2018激活码(转) - 老董 - 博客园
选用其中的破解补丁激活的方式,可以破解使用到2099年
2.基本流程
1)编写BuildProject相关的c#代码
在unity工程的Editor目录下,编写打包所需要的BuildProject.cs代码,基本操作可以简单归纳为:读取打包脚本的参数,根据参数更新相关设置,根据参数切换到对应的打包平台,执行打包操作。
部分参考代码如下:
static void BuildTest() { PreBuild(); BuildPlayer(); PostBuild(); } //构造之前 static void PreBuild() { UpdateParam(); }
2)编写python打包脚本
#!/user/bin/python #coding = utf-8 import subprocess import shutil import os UNITYPATH = "D:/Unity/Editor/Unity.exe" PROJECTPATH = "D:/WorkProgram/Python/UnityTest/UnityTest" platform = "android,win,ios" print("begin test") subprocess.call(UNITYPATH + " -quit " + " -batchmode " + " -projectPath " + PROJECTPATH + " -executeMethod BuildProject.BuildTest " + platform) print("end test")
3)执行打包脚本
在pycharm下可以执行执行该打包脚本即可,如果想设置为定时的打包,在windows下可以设置一个定时计划任务,在每天定时执行一次打包脚本即可
3.IOS自动打包
在ios平台上打包,需要将Unity的工程导出为XCode工程,然后在XCode里面进行打ipa包的处理。
如果想要执行自动打包,则需要进行一些特殊的操作,分为以下几个部分:
1)工具准备
在Mac上,首先需要安装一些基本的工具(python/pycharm/XCode默认已经安装):
provisioningFile查看工具:ProfilesManager
查看网上各种操作查看provisioning profiles的操作,这个工具可以实现在XCode里面运行,简易直观的查看
自动打包脚本github示例
这个脚本提供了基本的操作命令,可以在此基础上进一步的编写自己的打包脚本
2)python基本脚本
参考上面的自动打包脚本,测试和修改一些bug(填坑~),得到一个可以基本运行的自动将xcodeproject导出为ipa的运行脚本,保留如下:
#! /usr/bin/python # coding=utf-8 # -*- coding:utf8 -*- from optparse import OptionParser import subprocess import os import time #unity path and project path UNITYPATH = "/Applications/Unity/Unity.app/Contents/MacOS/Unity" PROJECTPATH = "******" # configuration for iOS build setting CONFIGURATION = "Release" SDK = "iphoneos" PROJECT = "*****" CACHAPATH = "*****" TARGET = "****" SCHEME = "Unity-iPhone" #桌面上创建出ipa EXPORT_MAIN_DIRECTORY = "~/Desktop/" EXPORT_OPTIONS_PLIST = "exportOptions.plist" def buildArchivePath(tempName): process = subprocess.Popen("pwd", stdout = subprocess.PIPE) (stdoutdata, stderrdata) = process.communicate() archiveName = "/%s.xcarchive" %(tempName) #print("name " + stdoutdata.strip().decode()) archivePath = CACHAPATH + archiveName return archivePath def cleanArchiveFile(archiveFile): cleanCmd ="rm -r %s" %(archiveFile) process = subprocess.Popen(cleanCmd, shell=True) process.wait() print("clean archiveFile: %s" %(archiveFile)) def buildExportDirectory(scheme): dateCmd = 'date "+%Y-%m-%d_%H-%M-%S"' process = subprocess.Popen(dateCmd, stdout= subprocess.PIPE, shell= True) (stdoutdata, stderrdata) = process.communicate() exportDirectory = "%s%s%s" %(EXPORT_MAIN_DIRECTORY, scheme, "-test1") print("export directory: " + exportDirectory) return exportDirectory def exportArchive(scheme, archivePath): exportDirectory = buildExportDirectory(scheme) exportCmd = "xcodebuild -exportArchive -archivePath %s -exportPath %s -allowProvisioningUpdates -exportOptionsPlist %s" %(archivePath, exportDirectory, EXPORT_OPTIONS_PLIST) process = subprocess.Popen(exportCmd, shell=True) (stdoutdata, stderrdata) = process.communicate() signReturnCode = process.returncode if signReturnCode != 0: print("export %s failed" %scheme) return "" else: return exportDirectory def buildProject(project, target, output): archivePath = buildArchivePath(SCHEME) print("arcivePath: "+ archivePath) process = subprocess.Popen('replace_provision_config', shell= True) process.wait() time1 = time.time() #archiveCmd = 'xcodebuild archive -archivePath %s' + archivePath + ' -scheme ' + "Unity-iPhone" + ' -quiet -configuration %s' + SCHEME archiveCmd = 'xcodebuild -project %s -scheme %s -configuration %s archive -archivePath %s -destination generic/platform=iOS' %(project, SCHEME, CONFIGURATION, archivePath) process = subprocess.Popen(archiveCmd, shell= True) process.wait() time2= time.time() print("finish archive cmd, used time: " + str(time2 - time1)) archiveReturnCode = process.returncode; if archiveReturnCode != 0: print("archive project %s failed " %project) cleanArchiveFile(archivePath) else: print("begin export archive") time3 = time.time() exportDirectory = exportArchive(SCHEME, archivePath) time4 = time.time() print("finish export archive, used time: " + str(time4 - time3)) cleanArchiveFile(archivePath) if exportDirectory != "": print("export archive success") def showNotification(title, subtitle): os.system("osascript -e 'display notification \"" + subtitle + "\" with title \"" + title + "\"'") #对xcode工程进行build def xcbuild(): output = os.path.expanduser("~") + '/Desktop/' + TARGET + '.ipa' #comments = options.comments print(output) buildProject(PROJECT, TARGET, output) #先执行unity的build.buildplayer,导出xcode工程 #在windows平台可以用call调用,但是在Mac下,用Popen执行,不然会报文件无法查找的错误 #在mac平台下,则需要执行popen的操作来执行命令行 def buildProjectResource(): print("先导出mac包") build = UNITYPATH + ' -quit -batchmode -projectPath ' + PROJECTPATH + ' -executeMethod BuildProject.BuildIOS ' buildCmd = build + "mac" #subprocess.call(buildCmd) time1 = time.time() #process = subprocess.Popen(buildCmd, shell = True) #process.wait() time2 = time.time() print("导出mac所用时间: " + str(time2-time1)) #再导出apk包 print("再导出apk") buildCmd = build + "android" time3 = time.time() #process = subprocess.Popen(buildCmd, shell = True) #process.wait() time4= time.time() print("导出apk所用时间: " + str(time4 - time3)) #再导出ios print("再导出xcode") buildCmd = build + "ios" time5 = time.time() process = subprocess.Popen(buildCmd, shell = True) process.wait() time6 = time.time() print("导出Xcode工程所用时间: " + str(time6 - time5)) def main(): buildProjectResource() xcbuild() if __name__ == '__main__': main()
其中标注为"*****"为你对应的项目的相关路径,可以自行填写。
对应的exportOptions.plist文件为:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>provisioningProfiles</key> <dict> <key>com.topjoy.pod1</key> <string>XC com topjoy pod1 </string> </dict> <key>method</key> <string>development</string> <key>compileBitcode</key> <true/> </dict> </plist>
3)执行打包脚本
执行打包脚本,目前会在unity导出xcode工程后中断,需要手动点击导出的xcode工程,然后设置signing中的appID,生成对应的provisioning profiles,然后继续执行脚本,可以得到最终的ipa文件,这个可以集合后面的打包工具,实现XCode中的签证设置,最终实现一键打包操作。
4.拓展性
目前只是一个简单的打包脚本,后续针对不同平台会有不同的配置,则需要对应的填充和拓展打包脚本以及对应的c#脚本来执行打包。
有任何疑问,可以留言讨论