接着上一篇文章, 自动生成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
|
#!/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
|
$
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
|
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
|
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
|
# #!/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等操作。。
有问题 给我留言吧, 嘿嘿!!!
- 本文固定链接: http://www.xuanyusong.com/archives/2734
- 转载请注明: 雨松MOMO 2014年06月11日 于 雨松MOMO程序研究院 发表