Unity脚本生成ipa或apk的方法

2016更新:本文写于2014。其中值得注意的是,建议默认使用python编写脚本,对跨平台有好处。而并非下文即将提及的、还不那么好地,使用bat、shell来编写。

基础概念

如果不关心概念只关心使用方法,可略过这里,直接去到“准备环境”、“脚本构建使用方法”。

能够使用Unity进行脚本生成ipa或apk(以下统称app)的核心前提是:

  • Unity运行时既包括了editor、也包括了compiler;
  • Unity运行时既能以界面形式运行、也能以命令行方式运行。可参见Unity命令行官方文档
  • Unity以命令行方式运行时,能够通过形如-executeMethod MyScript.MyMethod参数,调用Editor脚本工程里面的某一个静态方法,该静态方法可以引用UnityEngine库、UnityEditor库里的任意函数,包括关键的BuildPipeline.BuildPlayer函数。可参考BuildPlayer的官方文档
  • 也就是说,理论上任何在Unity编辑器里能实现的操作,都能通过命令行实现。(亲可以试一下使用命令行做一个Unity游戏出来:p)

所以,使用Unity进行脚本生成app的核心步骤是:

  1. 准备SDK环境。如果是生成apk,则机器(Mac或PC)先准备好Android SDK;如果是生成ipa,则Mac先安装好XCode
  2. 调用脚本,生成中间工程文件。脚本实际是运行Unity命令行,调用用户函数比如CommandBuild.Build函数,输入各类参数(比如-ios/-android的平台参数、比如-debug/-release的版本参数)
  3. 调用脚本,使用SDK将中间工程文件生成app。如果是生成apk,因为Android的开放性,Unity能够将这一步合到第2步中,所以生成apk也就不需要我们去搞第3步了;但如果是生成ipa,因为苹果限制必须使用XCode生成ipa,所以我们需要再用脚本调用XCode,将工程文件生成ipa。

准备环境

准备生成apk的环境

  1. 机器可以是PC或Mac。但这里只讨论PC。

  2. 下载java,并且添加java的安装路径到本机环境变量,方法可参考这里

  3. Android官网下载最新的Eclipse ADT

    注:可能出现点击下载按钮没反应的情况,可以更换浏览器再试试。
    注:ADT包括了EclipseIDE和SDK本身。事实上我们的确只需要SDK就好了,但试过下载SDK是不行的,因为缺少了里面的platforms。所以用下载工具下载ADT是个省时的选择。

  4. 解压下载好的压缩包,放到合适的地方。

  5. 打开Unity,Edit>Preferences>External Tools>Android SDK Location,然后选择你刚才解压文件夹中的sdk文件夹。

  6. 完毕。现在可以使用Unity构建了。

    注:如果构建中途,出现失败形如Error building Player: Win32Exception: ...zipalign.exe...CommandLine='4"的错误,可以把zipalignexe从sdk\build-tools\(你的版本)文件夹拷到sdk\tool文件夹。

准备生成ipa的环境

  1. 机器必须是Mac
  2. 到App Store下载并安装最新的XCode
  3. 准备好开发者帐号、开发者p12文件。(过程略)

脚本使用方法

生成apk

  1. 修改Environment.bat
    • 修改“unity”变量,指定里面的unity路径。
    • 修改“debugParam”变量,指定是-debug或者-release
  2. 执行UnityToApk.bat,等待执行完毕
  3. apk生成在KillerProject\Bin\Android文件夹下

生成ipa

  1. 修改UnityToXCode.sh里的“debugParam”变量,指定是-debug或者-release
  2. 执行UnityToIPA.sh生成ipa文件。也可以执行SvnUnityToIPA.sh即先更新SVN再生成ipa。

附脚本

apk相关脚本

Environment.bat

:: set your own Unity path
set unity="D:\Program Files (x86)\Unity\Editor\Unity.exe"
:: -debug or -release
set debugParam=-debug

set projectPath=%~dp0

UnityToApk.bat

rmdir /q Bin\Android
mkdir Bin\Android

call Environment.bat

echo "Start Build Unity to Apk"

%unity% -batchmode -projectPath %projectPath% -executeMethod CommandBuild.PreBuild %debugParam% -quit -logFile ./PreBuild.log
%unity% -batchmode -projectPath %projectPath% -executeMethod CommandBuild.Build %debugParam% -android -quit -logFile ./BuildApk.log


echo "End Build,please see log PreBuild.log and BuildApk.log"

ipa相关脚本

UnityToXCode.sh

#!/bin/bash

echo "Remove XCodeProject"

rm -rf XCodeProject

path=`pwd`
#-debug or -release
debugParam="-debug"

echo "Start Build Unity to XCodeProject"

/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -projectPath $path -executeMethod CommandBuild.PreBuild $debugParam -quit -logFile ./PreBuild.log
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -projectPath $path -executeMethod CommandBuild.Build $debugParam -ios -quit -logFile ./BuildXCodeProject.log

echo "End Build,please see log PreBuild.log and BuildXCodeProject.log"

XCodeToIPA.sh

#/bin/sh

usage()
{
    echo "usage: $0 AppName XCodeProject"
    echo "example: $0 Killer XCodeProject"
}

if [ $# -ne 2 ] ;then
    usage
    exit 1
fi

path=`pwd`
app_name=$1
xcodeproj_dir=$path/$2

#echo $app_name
#echo $xcodeproj_dir
#echo $path

if [ -d $xcodeproj_dir ] ;then
    echo "$xcode_dir exist"
else
    echo "dir $xcodeproj_dir doesn't exist"
    exit 1
fi

cd $xcodeproj_dir
xcodebuild -sdk iphoneos7.1

echo "end xcodebuild"

cd ./build
mkdir -p ipa/Payload
cp -r ./${app_name}.app ./ipa/Payload
cd ipa

echo "zip $app_name"
zip -r $app_name *

app_file=$path/${app_name}_$(date +%m%d_%H%M).ipa
mv ${app_name}.zip $app_file

echo "Build Successed ipa."
echo "$app_file"

通用Editor脚本代码

CommandBuild.cs

using UnityEngine;
using UnityEditor;

public class CommandBuild
{
    private static string[] ms_scenes =
    {
        "Assets/Scenes/KillerStarter.unity"
    };

    private static bool ms_isDebugBuild = false;
    private static BuildTarget ms_buildTarget = BuildTarget.Android;

    private static string XCODE_PROJECT_NAME = "XCodeProject";
    private static string BUILD_OUTPUT_ANDROID = "Bin/Android/";

    private static void UpdateBuildFlag()
    {
        string[] args = System.Environment.GetCommandLineArgs();
        foreach(string oneArg in args)
        {
            if (oneArg != null && oneArg.Length > 0)
            {
                if (oneArg.ToLower().Contains("-debug"))
                {
                    Debug.Log("\"-debug\" is detected, switch to debug build.");
                    ms_isDebugBuild = true;
                    return;
                }
                else if (oneArg.ToLower().Contains("-release"))
                {
                    Debug.Log("\"-release\" is detected, switch to release build.");
                    ms_isDebugBuild = false;
                    return;
                }
            }
        }

        if (ms_isDebugBuild)
        {
            Debug.Log("neither \"-debug\" nor \"-release\" is detected, current is to debug build.");
        }
        else
        {
            Debug.Log("neither \"-debug\" nor \"-release\" is detected, current is to release build.");
        }
    }
    private static void UpdateBuildTarget()
    {
        string[] args = System.Environment.GetCommandLineArgs();
        foreach (string oneArg in args)
        {
            if (oneArg != null && oneArg.Length > 0)
            {
                if (oneArg.ToLower().Contains("-android"))
                {
                    Debug.Log("\"-android\" is detected, switch build target to android.");
                    ms_buildTarget = BuildTarget.Android;
                    return;
                }
                else if (oneArg.ToLower().Contains("-iphone"))
                {
                    Debug.Log("\"-iphone\" is detected, switch build target to iphone.");
                    ms_buildTarget = BuildTarget.iPhone;
                    return;
                }
                else if (oneArg.ToLower().Contains("-ios"))
                {
                    Debug.Log("\"-ios\" is detected, switch build target to iphone.");
                    ms_buildTarget = BuildTarget.iPhone;
                    return;
                }
            }
        }

        Debug.Log("neither \"-android\", \"-ios\" nor \"-iphone\" is detected, current build target is: " + ms_buildTarget);
    }
    public static void PreBuild()
    {
        Debug.Log("PreBuild");
        UpdateBuildFlag();
        SetKgfDebugActive(ms_isDebugBuild);
    }
    public static void Build()
    {
        Debug.Log("Build");
        UpdateBuildTarget();

        BuildOptions buildOption = BuildOptions.None;
        if (ms_isDebugBuild)
        {
            buildOption |= BuildOptions.Development;
            buildOption |= BuildOptions.AllowDebugging;
            buildOption |= BuildOptions.ConnectWithProfiler;
        }
        else
        {
            buildOption |= BuildOptions.None;
        }

        string locationPathName;
        if(BuildTarget.iPhone == ms_buildTarget)
        {
            locationPathName = XCODE_PROJECT_NAME;
        }
        else
        {
            locationPathName = BUILD_OUTPUT_ANDROID;
            System.DateTime time = System.DateTime.Now;
            locationPathName += "killer_" + time.Month.ToString("D2") + time.Day.ToString("D2") +
                "_" + time.Hour.ToString("D2") + time.Minute.ToString("D2") + ".apk";
        }
        BuildPipeline.BuildPlayer(ms_scenes, locationPathName, ms_buildTarget, buildOption);
    }
    public static void PostBuild()
    {
        Debug.Log("PostBuild");
    }

    private static void SetKgfDebugActive(bool activated)
    {
        ///非重点,略
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容