接着上一篇文章, 自动生成framework,这篇文章我把shell自动化打包ipa整理了一下,希望大家喜欢,嘿嘿。。 建议大家先看一下上一篇文章。 https://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字符串作为文件名。
#!/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脚本中我调用了
$UNITY_PATH -projectPath $PROJECT_PATH -executeMethod ProjectBuild.BuildForIPhone project-$1 -quit
它的意思就是自动打开unity,然后打开你的游戏工程,然后调用ProjectBuild类中的BuildForIPhone的这个方法,然后关闭unity。ProjectBuild类是我自己写的,大家也可以定制自己的类 和方法,static的就可以。
这里有个比较重要的参数 project-$1 这个参数就是外面我们传进来的 91 字符串。 这个字符串很重要,因为工程里面构建的时候需要根据不同的渠道打包不同的资源 包名 文件名 等等。我们在看看 ProjectBuild.cs
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行之间的代码。
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 *)urlr{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我没能成功, 自己又修改了一点。。
# #!/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程序研究院 发表





我把Xcode升到了8.1后打包就报这个错,请问要怎么解决呢? 我去修改Unity4XC.xcplugin提示修改不了,需要在终端中修改,可在终端中我并不知道怎么修改。** CLEAN SUCCEEDED **/Users/chenyue_mac/Documents/testScene/1112016-11-03 11:11:06.250 xcodebuild[2665:173701] [MT] PluginLoading: Required plug-in compatibility UUID DA4FDFD8-C509-4D8B-8B55-84A7B66AE701 for plug-in at path ‘~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/Unity4XC.xcplugin’ not present in DVTPlugInCompatibilityUUIDs=== BUILD TARGET Unity-iPhone OF PROJECT Unity-iPhone WITH THE DEFAULT CONFIGURATION (Release) ===Check dependenciesUnity-iPhone requires a provisioning profile. Select a provisioning profile for the “Release” build configuration in the project editor.Code signing is required for product type ‘Application’ in SDK ‘iOS 10.1’** BUILD FAILED **The following build commands failed:Check dependencies(1 failure)ChenYue-MacdeiMac:~ chenyue_mac$
我把Xcode升到了8.1后打包就报这个错,请问要怎么解决呢? 我去修改Unity4XC.xcplugin提示修改不了,需要在终端中修改,可在终端中我并不知道怎么修改。** CLEAN SUCCEEDED **/Users/chenyue_mac/Documents/testScene/1112016-11-03 11:11:06.250 xcodebuild[2665:173701] [MT] PluginLoading: Required plug-in compatibility UUID DA4FDFD8-C509-4D8B-8B55-84A7B66AE701 for plug-in at path ‘~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/Unity4XC.xcplugin’ not present in DVTPlugInCompatibilityUUIDs=== BUILD TARGET Unity-iPhone OF PROJECT Unity-iPhone WITH THE DEFAULT CONFIGURATION (Release) ===Check dependenciesUnity-iPhone requires a provisioning profile. Select a provisioning profile for the “Release” build configuration in the project editor.Code signing is required for product type ‘Application’ in SDK ‘iOS 10.1’** BUILD FAILED **The following build commands failed: Check dependencies(1 failure)ChenYue-MacdeiMac:~ chenyue_mac$
我遇到的也是这个问题。报错也完全一样。尝试了XUPorter去更改设定 但是目前毫无头绪
请问这个问题解决了么?怎么解决的?
雨松大大,请问mac版的U3D突然打包不了IOS工程是怎么回事?点击build之后U3D毫无反应,以前都能打包的,U3D版本是4.6.7 换了几个版本还是这样
CompileC build/Unity-iPhone.build/Release-iphoneos/Unity-iPhone.build/Objects-normal/armv7/UnityAppController.o Classes/UnityAppController.mm normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler 请问这个怎么解决?
CompileC build/Unity-iPhone.build/Release-iphoneos/Unity-iPhone.build/Objects-normal/armv7/UnityAppController.o Classes/UnityAppController.mm normal armv7 objective-c++ com.apple.compilers.llvm.clang.1_0.compiler 请问这个怎么解决?
有个问题,我知道结果了,但我更想知道为什么会发生,怎么能这么实现的?是想好了,一直尝试的结果么?这样的话会比较累,如果是写iphone的人,或者一个程序老猿,写这种互调语法,倒不奇怪,可是雨松一直是写u3d,估计2年前与松野写不出这样的代码,就好像java 用jni调用c 一样,程序是互通的,很多人懂,但更多人不懂,也肯定会有一个过程,程序员由不懂变得秒懂,我真想知道是什么促成了这种转变
有个问题,我知道结果了,但我更想知道为什么会发生,怎么能这么实现的?是想好了,一直尝试的结果么?这样的话会比较累,如果是写iphone的人,或者一个程序老猿,写这种互调语法,倒不奇怪,可是雨松一直是写u3d,估计2年前与松野写不出这样的代码,就好像java 用jni调用c++一样,程序是互通的,很多人懂,但更多人不懂,也肯定会有一个过程,程序员由不懂变得秒懂,我真想知道是什么促成了这种转变
这个问题太高深了。 呵呵, 我也不知道怎么回答你。。
最近入手了太mac pro,正准备用用
不错不错,又一个好的u3d文章
成功了,感谢大神!
请问你怎么解决的下面那个问题的
大神,我在使用shell生成ipa包的成,最后有一个错误提示:error: Specified application doesn’t exist or isn’t a bundle directory : ‘/Users/pza/Desktop/auto_test/auto/build/*.app’,并且spa包没有生成出来,请大神帮忙解决一下,谢谢!!!
请问你解决了吗?
请问你怎么解决的 我现在也碰到这个问题
请问解决了吗
估计你们项目比较大,(用的都是破解版么?),app没生成
在shell里面使用xcrun -sdk iphoneos PackageApplication把app自动编译成ipa文件的时候报这个错误一直找不到原因 error: Specified application doesn’t exist or isn’t a bundle directory : ‘–v’
第一次使用shell,出现如下错误:
ZhongdpmatoMacBook-Pro:downjoyPayDemo 6 Zhongdp$
ZhongdpmatoMacBook-Pro:downjoyPayDemo 6 Zhongdp$ xcrun -sdk iphoneos PackageApplication -v ./${appdirname}/*.app -o ${build_path}/ipa-build/${ipa_name}.ipa || exit
error: Specified application doesn’t exist or isn’t a bundle directory : ‘./Release-iphoneos/*.app’
logout
请大神,这个是什么错误?qq:780713992
大神,为什么读取app_icon,游戏图标的时候,在有些机型的icon会有白边呢,直接读取SDK里面配置的icon,就不会i有呢
你说的是半月牙吗?
雨松大神,我用.net 创建了一个 wcf服务并部署到 IIS服务器上,然后我创建了一个动态库dll。在这个动态库中添加了这个wcf服务的服务引用。我将这个动态库dll引用到自己的 windows 版 unity工程中,并进行相关调用,是可以正常访问我的那个wcf服务的。 然后用 unity 打包成安卓apk,在手机上运行,也能正常访问。 将 这个动态库dll引用到 unity(mac版) 工程中,直接在工程中运行也能访问wcf服务。但是在 准备 将 unity(mac版) 工程 转换成 xcode工程 打包时,在这个转换过程中 却报错了。错误信息部分如下:Cross compilation job Mono.WebBrowser.dll failed.UnityEngine.UnityException: Failed AOT cross compiler: /Applications/Unity/Unity.app/Contents/PlaybackEngines/iossupport/Tools/OSX/mono-xcompiler-wrapper.sh –aot=full,asmonly,nodebug,nrgctx-trampolines=8096,nimt-trampolines=8096,ntrampolines=4048,static,outfile=”Mono.WebBrowser.dll.s” “Mono.WebBrowser.dll” 这是什么原因导致的呢,求大神指导。
android用 .so iOS用 .a
xcodebuild -project Unity-iPhone.xcodeproj -scheme Unity-iPhone -destination generic/platform=ios archive -archivePath $archivePath #xcrun -sdk iphoneos PackageApplication -v ${build_path}/*.app -o ${build_path}/${ipa_name}.ipaxcodebuild -exportArchive -archivePath $archivePath -exportPath ${build_path}/${ipa_name}.ipa -exportFormat ipa -exportProvisioningProfile ‘iOSTeam Provisioning Profile: ‘aaaaa’这个打包出来和手动的一样大
打包回大几十M的问题,有人解决了吗
xcodebuild -project Unity-iPhone.xcodeproj -target Unity-iPhone -configuration Release PROVISIONING_PROFILE=”$provUUID” CODE_SIGN_IDENTITY=”$signCer” DEPLOYMENT_POSTPROCESSING=YES STRIP_INSTALLED_PRODUCT=YES SEPARATE_STRIP=YES COPY_PHASE_STRIP=YES codesign -d –entitlements – “$appPath”xcrun -sdk iphoneos PackageApplication -v “$appPath” -o “$ipaPath” –sign “$signCer” –embed “$mobileprovision”
我试试 ,多谢雨松大神
几个新参数好头疼,大神方便解释下参数要不要绝对路径,或者要不要带后缀吗
奇怪,,其实我的自动打包和手动比就大10M。
大神我问下 在xcodebuild || exit 之后我加了CODE_SIGN_IDENTITY=iPhone Developer:taoye ,是为了希望用shell自动选择开发者账号,就不用进去设置了再build,但是发现怎么都不成功,请问有什么好方法设置开发者账号们?
我现在是在shell里面做的。。
我这个也是shell做的啊,我想问shell怎么来设置开发者账号,另外用shell打包的ipa比 我直接archive出来的ipa 要大一点 这是为什么呢?
可能是参数 没写对。。
MoMo大神,资源包下载了,但是导入不进去啊,我的unity是4.6.6f2,不知道是不是版本问题,如果是的话,请问能不能提供一下这个版本的package啊
啊,解决了,是因为资源包路径有中文,晕
OK
你好,我经过测试成功了, 但是每次执行命令,unity打开后会重新import 资源,非常慢.
不用, 你在本地先把平台切好。 以后就不用import了