您的位置:首页 > 移动开发 > Unity3D

Unity3D研究院之IOS全自动打包生成ipa

2016-06-12 19:49 771 查看
接着上一篇文章, 自动生成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脚本中我调用了

C#

1

$UNITY_PATH
-projectPath
$PROJECT_PATH
-executeMethod
ProjectBuild.BuildForIPhone
project-$1
-quit

它的意思就是自动打开unity,然后打开你的游戏工程,然后调用ProjectBuild类中的BuildForIPhone的这个方法,然后关闭unity。[b]ProjectBuild类是我自己写的,大家也可以定制自己的类 和方法,static的就可以。[/b]

这里有个比较重要的参数 project-$1 这个参数就是外面我们传进来的 91 字符串。 这个字符串很重要,因为工程里面构建的时候需要根据不同的渠道打包不同的资源 包名 文件名 等等。我们在看看 ProjectBuild.cs

C#

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代码。。 我们在回到[b]XUPorter XCodePostProcess.cs这个类里面, 如果没看过我上一篇文章的 我建议看一下。。[/b]

下面的代码 上一篇文章我已经介绍的很清楚了, 这里就不赘述了。主要看 54行 – 64行之间的代码。

C#

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程序研究院 发表
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: