0. 概述
本文主要针对项目中自动打包过程进行调研, 实现用 python 脚本来打出 win/android/ios 三个平台下的游戏运行包.
1. 工具安装
首先基本的工具需要安装, Unity, python, 如果需要修改 python 脚本, 则需要安装一下 pycharm, 对应的链接:
Download Python https://www.python.org/downloads/
用最新版本即可
pycharm 安装 https://www.jetbrains.com/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 https://github.com/shaojiankui/ProfilesManager
查看网上各种操作查看 provisioning profiles 的操作, 这个工具可以实现在 XCode 里面运行, 简易直观的查看
自动打包脚本 github 示例 https://github.com/carya/Util
这个脚本提供了基本的操作命令, 可以在此基础上进一步的编写自己的打包脚本
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# 脚本来执行打包.
有任何疑问, 可以留言讨论
参考文章:
iOS 自动打包并发布脚本 http://liumh.com/2015/11/25/ios-auto-archive-ipa/
Xcode9 xcodebuild 命令行打包遇到的坑与解决方案 https://blog.csdn.net/yuanmengong886/article/details/78214978
iOS 自动构建命令 --xcodebuild https://www.jianshu.com/p/3f43370437d2
来源: https://www.cnblogs.com/zblade/p/9298905.html