接着上一篇文章, 自动生成framework,这篇文章我把shell自动化打包ipa整理了一下,希望大家喜欢,嘿嘿。。 建议大家先看一下上一篇文章。 http://www.xuanyusong.com/archives/2720
首先我们要先搞清楚nity全自动打包的重要步骤。
1.自动生成xcode工程。
2.自动生成.ipa和dsym文件。
3.上传appstore(本篇略)
首先我们在做渠道包时,一般每个渠道都有自己一些特殊的需求,比如 游戏名子 、游戏图标、SDK、等等。那么我在在做自动化打包的工具时,需要把渠道作为参数传入shell脚本中,如下图所示开始运行我的shell脚本,这里只接收一个参数,其实就是告诉脚本你要打什么渠道的包,这里我写91。
脚本比较简单,原理就是先生成xcode工程,然后接着生成.ipa 。 代码中的$1 就表示我传入的第一个参数 91字符串。
UNITY_PATH :就是unity安装的路径, 如果你不改Unity的名子Mac上就会是这个路径。
PEOJECT_PATH:这个是你游戏工程的路径。。就是 Assets/上一级的哪个路径。。
BUILD_IOS_PATH:这个是我打包生成ipa的一个脚本,后面我会细说我目前把这个脚本放在我的游戏工程里, 所以他是一个相对路径。
XCODE_PATH:这个是生成xcode工程的路径,因为可能有很多渠道,所以我就传入的91字符串作为文件名。
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 |
#!/bin/sh #参数判断 if [ $# != 1 ];then echo "需要一个参数。 参数是游戏包的名子" exit fi #UNITY程序的路径# UNITY_PATH=/Applications/Unity/Unity.app/Contents/MacOS/Unity #游戏程序路径# PROJECT_PATH=/Users/MOMO/commond #IOS打包脚本路径# BUILD_IOS_PATH=${PROJECT_PATH}/Assets/buildios.sh #生成的Xcode工程路径# XCODE_PATH=${PROJECT_PATH}/$1 #将unity导出成xcode工程# $UNITY_PATH -projectPath $PROJECT_PATH -executeMethod ProjectBuild.BuildForIPhone project-$1 -quit echo "XCODE工程生成完毕" #开始生成ipa# $BUILD_IOS_PATH $PROJECT_PATH/$1 $1 echo "ipa生成完毕" |
脚本执行的过程,无需打开unity工程,它会自动打开unity工程,自动构建xcode工程,自动关闭unity工程,然后自动打包。。如下图所示,看到这样的字样你的IPA就生成完毕了。
然后你的.ipa和dsym文件就安安静静的放在build文件夹下,项目根目录/91/build文件夹下面,dsym文件也放在下面,如果你的渠道包比较多的话,你可以把它们统一移动到一个文件夹下面。还有dsym一定要打出来,因为只有dsym 和 .crash文件才能解析出 c#代码中哪个调用方法出的错, 以后有时间了我会整理以下dsym和.crash文件怎么解析出c#错误的堆栈来。。
ipa是出来了, 不过我们还是要看看它到底是怎么出来了。。在shell脚本中我调用了
1 2 3 |
$UNITY_PATH -projectPath $PROJECT_PATH -executeMethod ProjectBuild.BuildForIPhone project-$1 -quit |
它的意思就是自动打开unity,然后打开你的游戏工程,然后调用ProjectBuild类中的BuildForIPhone的这个方法,然后关闭unity。ProjectBuild类是我自己写的,大家也可以定制自己的类 和方法,static的就可以。
这里有个比较重要的参数 project-$1 这个参数就是外面我们传进来的 91 字符串。 这个字符串很重要,因为工程里面构建的时候需要根据不同的渠道打包不同的资源 包名 文件名 等等。我们在看看 ProjectBuild.cs
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
using System.Collections; using System.IO; using UnityEditor; using UnityEngine; using System.Collections.Generic; using System; class ProjectBuild : Editor{ //在这里找出你当前工程所有的场景文件,假设你只想把部分的scene文件打包 那么这里可以写你的条件判断 总之返回一个字符串数组。 static string[] GetBuildScenes() { List<string> names = new List<string>(); foreach(EditorBuildSettingsScene e in EditorBuildSettings.scenes) { if(e==null) continue; if(e.enabled) names.Add(e.path); } return names.ToArray(); } //得到项目的名称 public static string projectName { get { //在这里分析shell传入的参数, 还记得上面我们说的哪个 project-$1 这个参数吗? //这里遍历所有参数,找到 project开头的参数, 然后把-符号 后面的字符串返回, //这个字符串就是 91 了。。 foreach(string arg in System.Environment.GetCommandLineArgs()) { if(arg.StartsWith("project")) { return arg.Split("-"[0])[1]; } } return "test"; } } //shell脚本直接调用这个静态方法 static void BuildForIPhone() { //打包之前先设置一下 预定义标签, 我建议大家最好 做一些 91 同步推 快用 PP助手一类的标签。 这样在代码中可以灵活的开启 或者关闭 一些代码。 //因为 这里我是承接 上一篇文章, 我就以sharesdk做例子 ,这样方便大家学习 , PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iPhone, "USE_SHARE"); //这里就是构建xcode工程的核心方法了, //参数1 需要打包的所有场景 //参数2 需要打包的名子, 这里取到的就是 shell传进来的字符串 91 //参数3 打包平台 BuildPipeline.BuildPlayer(GetBuildScenes(), projectName, BuildTarget.iPhone, BuildOptions.None); } } |
你可以在打包之前 去修改projectSetting的参数, 比如 包名 游戏名 icon 等等 http://docs.unity3d.com/Manual/class-PlayerSettings.html
OK shell脚本中就直接开始构建你的xcode工程。还记得上一篇文章我提到的XUPorter吗?它的原理就是当Xcode打完完毕后开始动态的编辑 framework plist oc代码。。 我们在回到XUPorter XCodePostProcess.cs这个类里面, 如果没看过我上一篇文章的 我建议看一下。。
下面的代码 上一篇文章我已经介绍的很清楚了, 这里就不赘述了。主要看 54行 – 64行之间的代码。
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
using UnityEngine; #if UNITY_EDITOR using UnityEditor; using UnityEditor.Callbacks; using UnityEditor.XCodeEditor; using System.Xml; #endif using System.IO; public static class XCodePostProcess { #if UNITY_EDITOR [PostProcessBuild (100)] public static void OnPostProcessBuild (BuildTarget target, string pathToBuiltProject) { if (target != BuildTarget.iPhone) { Debug.LogWarning ("Target is not iPhone. XCodePostProcess will not run"); return; } //得到xcode工程的路径 string path = Path.GetFullPath (pathToBuiltProject); // Create a new project object from build target XCProject project = new XCProject (pathToBuiltProject); // Find and run through all projmods files to patch the project. // Please pay attention that ALL projmods files in your project folder will be excuted! //在这里面把frameworks添加在你的xcode工程里面 string[] files = Directory.GetFiles (Application.dataPath, "*.projmods", SearchOption.AllDirectories); foreach (string file in files) { project.ApplyMod (file); } //增加一个编译标记。。没有的话sharesdk会报错。。 project.AddOtherLinkerFlags("-licucore"); //设置签名的证书, 第二个参数 你可以设置成你的证书 project.overwriteBuildSetting ("CODE_SIGN_IDENTITY", "iPhone Developer: Yu Song (XXXXXXXXXX)", "Release"); project.overwriteBuildSetting ("CODE_SIGN_IDENTITY", "iPhone Developer: Yu Song (XXXXXXXXXX)", "Debug"); // 编辑plist 文件 EditorPlist(path); //编辑代码文件 EditorCode(path); // Finally save the xcode project project.Save (); //上面的介绍 我已经在上一篇文章里面讲过, 这里就不赘述 。。 //那么当我们打完包以后 如果需要根据不同平台 替换 不同的framework plist oc 包名 等等。。。 //这里输出的projectName 就是 91 Debug.Log(projectName); if(projectName== "91") { //当我们在打91包的时候 这里面做一些 操作。 } } public static string projectName { get { foreach(string arg in System.Environment.GetCommandLineArgs()) { if(arg.StartsWith("project")) { return arg.Split("-"[0])[1]; } } return "test"; } } private static void EditorPlist(string filePath) { XCPlist list =new XCPlist(filePath); string bundle = "com.yusong.momo"; string PlistAdd = @" <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLIconFile</key> <string>Icon@2x</string> <key>CFBundleURLName</key> <string>"+bundle+@"</string> <key>CFBundleURLSchemes</key> <array> <string>ww123456</string> </array> </dict> </array>"; //在plist里面增加一行 list.AddKey(PlistAdd); //在plist里面替换一行 list.ReplaceKey("<string>com.yusong.${PRODUCT_NAME}</string>","<string>"+bundle+"</string>"); //保存 list.Save(); } private static void EditorCode(string filePath) { //读取UnityAppController.mm文件 XClass UnityAppController = new XClass(filePath + "/Classes/UnityAppController.mm"); //在指定代码后面增加一行代码 UnityAppController.WriteBelow("#include \"PluginBase/AppDelegateListener.h\"","#import <ShareSDK/ShareSDK.h>"); //在指定代码中替换一行 UnityAppController.Replace("return YES;","return [ShareSDK handleOpenURL:url sourceApplication:sourceApplication annotation:annotation wxDelegate:nil];"); //在指定代码后面增加一行 UnityAppController.WriteBelow("UnityCleanup();\n}","- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url\r{\r return [ShareSDK handleOpenURL:url wxDelegate:nil];\r}"); } #endif } |
OK 到这一步我们的xcode工程已经做完。。 然后Shell 脚本开始 生成.ipa文件。
#开始生成ipa#
$BUILD_IOS_PATH $PROJECT_PATH/$1 $1
上面代码的意思 就是 去调用我工程里面的buildios.sh文件。 需要传入两个参数 一个是 xcode工程的地址, 一个是 ipa的名子。。。 这个脚本我参考了 http://blog.csdn.net/ccf0703/article/details/7999112 这篇文章, 但是 最后生成ipa我没能成功, 自己又修改了一点。。
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 |
# #!/bin/bash #参数判断 if [ $# != 2 ];then echo "Params error!" echo "Need two params: 1.path of project 2.name of ipa file" exit elif [ ! -d $1 ];then echo "The first param is not a dictionary." exit fi #工程路径 project_path=$1 #IPA名称 ipa_name=$2 #build文件夹路径 build_path=${project_path}/build #清理# xcodebuild clean #编译工程 cd $project_path xcodebuild || exit #打包 下面代码我是新加的# xcrun -sdk iphoneos PackageApplication -v ${build_path}/*.app -o ${build_path}/${ipa_name}.ipa |
OK,到这一步我们的教程就完毕了。。因为工程中涉及到我项目用的证书啊什么的,所以我不能给出来。 所以我把你需要修改的地方列出来。
1.在关闭unity的状态下 运行 build脚本。 直接把build.sh 拖入终端里 然后空格 加一个你定义的参数 下图是我测试工程的目录结构。
2.在XCodePostProcess.cs 里面 把证书 还有包名 修改成你的。。
3.你的shell脚本需要给它权限 代码很简单 chmod +x build
4.我的工程下载地址:http://pan.baidu.com/s/1gd242dl
如果我说的上面三点你都修改完毕, 那么这个代码必然会帮你自动生成.ipa
本篇文章我主要给出一个大概的思路,大家可以在我的思路下去拓展,比如 一键打包多个渠道、 打包完毕后自动上传svn等操作。。
有问题 给我留言吧, 嘿嘿!!!
- 本文固定链接: https://www.xuanyusong.com/archives/2734
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
大神你好,我现在需要往里面添加一个swift文件,并建立bridge,这个操作有办法自动化吗?
为啥设置开发者证书和账号没用呀,好像成功过 第二次就没成功了
打包脚本变化了很多
-executeMethod可以给C#传个参数吗?
能更新下?现在下了你的demo工程无法打出包xcodebuild: error: IOSBuildToolTest/Assets/shell does not contain an Xcode project
Unity打包iOS, 安装后容量很大?而Android却很少,请问有没有同仁有这样的问题烦恼?
ios 空工程已经15M了吧。
bogon:~ jiaojunhao$ /Users/jiaojunhao/Desktop/UnityProjects/Buildipa/Assets/shell/build.py 91XCODE工程生成完毕The first param is not a dictionary.ipa生成完毕这异常是那里出问题,参照文章修改如下:修改1:build.sh没有这文件撒,shell里只有build.py拖到终端里。修改2:在XCodePostProcess.cs 里面 把证书 还有包名 修改成你的。。 我这里用是开发者账号等的证书,常用名称:Phone Distribution: Guizhou Yun Chen Tuo Yuan Network Technology Co., Ltd. (HXQSKN4F99) 。修改包名没看到修改的地方 if(projectName== “91”) 这个是判断输入的时候判断用的。修改3:你的shell脚本需要给它权限 代码很简单 chmod +x build,这权限怎么添加?用的是下载的工程源码修改的。修改4:build.py 里 修改了路径#UNITY程序的路径#UNITY_PATH=/Applications/Unity5.3.4f1/Unity.app/Contents/MacOS/Unity#游戏程序路径#PROJECT_PATH=/Users/jiaojunhao/Desktop/UnityProjects/NewHZZX2.0/NewHZZX请指教有那一步错了!
请问XUPorter是自己新建了一个xcode工程,然后在修改吗?还是在unity3d生成的xcode工程基础上进行修改的?我的项目代码是单独分开的,最终生成的是一个dll加到unity3d里面去,用你这种方法导出的xcode项目,会报错:dll里面的方法引用都找不到。不知道为何