天天看点

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

Unity Jenkins SVN 基础全攻略

Unity Jenkins SVN 基础全攻略

  • Unity Jenkins SVN 基础全攻略
    • 使用环境
    • 1 使用 Jenkins
      • 1.1 安装 Jenkins
      • 1.2 Jenkins 工作目录
      • 1.3 Jenkins 基础插件
    • 2 创建 Unity 任务
      • 2.1 Freestyle Project
        • 2.1.1 使用插件 Unity3d plugin
        • 2.1.2 使用 Batch 命令
      • 2.2 Pipeline
    • 3 加入SVN
    • 4 简单的用户管理
    • 5 细节与坑
      • 5.1 控制台中文乱码
      • 5.2 Jenkins 会定时清空工作目录
      • 5.3 EditorUserBuildSettings.SwitchActiveBuildTarget 不可再命令行下使用
      • 5.4 Unity Android 出包失败
    • 6 插件推荐与开发建议

使用环境

本文所使用的环境如下:

操作系统:Windows10

Jenkins版本:Jenkins 2.303.1 LTS

SVN版本:TortoiseSVN 1.14.1

Unity版本:Unity2019

1 使用 Jenkins

1.1 安装 Jenkins

首先前往官网下载Jenkins

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

选择 Windows ,下载得到

jenkins.msi

,打开根据指导进行安装即可(缺少 JAVA 运行环境请自行安装)。

请严格按照官方安装步骤进行安装!!!(一定不能装在LocalSystem上!不然有你好果汁吃~)

安装完后会弹出页面,稍微等待一下下。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

这里建议记一下这个路径备用,根据提示找到对应路径下的密码复制到下面(我这个路径属实是偷懒受害者)。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

这里我们可以先不着急安装插件,直接关掉这个页面(当然这里也可以提前把插件装上)。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

点击

开始使用Jenkins

后,我们就可以正式进入主界面啦~

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

进入Jenkins第一件重要的事,就是改密码!不然每次登录都得去复制辣么长一串。

点击右上角用户。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

选择

Configure

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

找到

Password

修改密码后保存。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

1.2 Jenkins 工作目录

在我们安装 Jenkins 的时候,它已经为我们默认创建了工作目录。还记得刚才让你去复制密码的路径吗?以我为例打开

\AppData\Local\Jenkins

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略
  • .jenkins

    :工作空间的主要内容
  • war

    :Jenkins 服务启动时,解压出来的war文件
  • jenkins.pid

    :保存着运行时的进程ID

我们进入

.jenkins

文件夹。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略
  • job

    :保存每个 Jenkins 任务的构建信息,比如log日志啥的。
  • logs

    :保存着 Jenkins 自身的 log 信息
  • nodes

    :保存代理节点的信息
  • plugins

    :保存 Jenkins 的插件
  • updates

    :保存 Jenkins 更新目录
  • userContent

    :可通过

    /userContent

    进行访问,不常用
  • user

    :保存用户账户信息
  • workspace

    :这里会存放不同任务的工程目录,图中没有是因为目前我们还没有创建任务,通过SVN拉取工程。

一般来说,我们不希望Jenkins的工作目录存放在C盘下,我们需要改变Jenkins的工作目录所在位置。

在修改之前,我们需要停止Jenkins服务。

首先启动

cmd

,切换路径到Jenkins的安装目录下。输入

net stop jenkins

停止Jenkins服务。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

如果输入指令后出现:

发生系统错误 5。   

拒绝访问。
           

请以管理员模式启动

cmd

,再试一遍。

然后我们打开本目录下的

jenkins.xml

文件。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

找到定义

JENKINS_HOME

值的这一行,这行指明了工作目录路径:

修改后面的

value

值为自己的工作目录路径,例如我改到了

E:\JenkinsProject

,对应则修改如下。

这里,最好将文件后面的

war

解压位置和

pid

文件位置一起改了,一次性迁移干净。

...
<arguments>-Xrs -Xmx256m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "D:\Jenkins\jenkins.war" --httpPort=8080 --webroot="E:\JenkinsProject\war"</arguments>
...
<pidfile>E:\JenkinsProject\jenkins.pid</pidfile>
           

修改后,将旧的

.jenkins/

目录下所有的数据文件迁移过去(war 和 pid 重新生成就行了)。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

最后,再命令行中敲入以下语句,启动

Jenkins

服务。

net start Jenkins
           

我们可以从侧边依次点击

Manage Jenkins > Configure System

,可以看到工作目录确实修改成功了!

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

这里再额外说一下,以我这种方式启动

Jenkins

服务,直接添加或修改环境变量

JENKINS_HOME

是没有效果的。如果想要自己的环境变量生效,需要注释掉

Jenkins.xml

中的关于

JENKINS_HOME

定义的这一行。

这也算是个老问题了:JENKINS-13530

1.3 Jenkins 基础插件

现在,我们来到

Manage Jenkins > Manage Plugins

安装一些基础插件,其余插件我们用到的时候再添加。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

Localization: Chinese (Simplified)

不习惯英文的朋友,可以安装这个简体中文语言包(虽然并没有完全汉化)

Subversion

使用 SVN 必备的插件(不同版本可能会有不同的名字,可点进链接确认)

初次之外,还有一些其他的SVN的插件,查看其具体功能,自行安装(注意!你最好清楚插件的功能,不要梭哈全装上,例如:SVN1.4 和 最新的SVN版本,在文件结构上是有很大差别的。)

Unity3d plugin

这个可以帮助你更简单地通过命令行来调用

Unity编辑器

,并且有实时log的功能。

咱先装这三个,点击

Install without restart

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

可以看到关联的插件也加入了下载列表中,然后等待!

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

如果下载失败,或下载缓慢,在这个页面的旁边找到

Advanced

,在

Update Site

一栏填入镜像链接,再次下载试试。

https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json (可去网上多找几个试试)
           

下载完后,使用命令

restart

,访问

http://localhost:8080/restart

重启一遍(中间是你自己的Jenkins网址)。

2 创建 Unity 任务

为了方便演示,我在本地创建一个SVN仓库

file:///E:/SVNRepo

,并新建Unity工程

E:\Unity_Jenkins

上传到此处。

然后在

Editor

目录下创建

BatchMode.cs

public class BatchMode {
    static Dictionary<string, string> command = new Dictionary<string, string>();
    //外部调用接口
    public static void Build() {
        command.Clear();
        string[] args = System.Environment.GetCommandLineArgs();
        foreach (string arg in args) {
            string[] s = arg.Split('='); 
            if (s.Length < 2) continue;
            command.Add(s[0],s[1].Replace("\"", ""));
        } 
#if UNITY_STANDALONE
        BuildWindows();
#elif UNITY_ANDROID 
        Debug.Log("Android");
#elif UNITY_IOS 
#endif
    } 
    // 我们以windows为例
    // Android主要有几个坑卡着大家(后面细说),其他与windows同理
    private static void BuildWindows() {
        List<string> scenes = new List<string>();
        // 获取场景信息
        foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes){
            if (!scene.enabled) continue;
            scenes.Add(scene.path);
        }  
        BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
        buildPlayerOptions.scenes = scenes.ToArray(); 
        buildPlayerOptions.locationPathName = command["output"];
        buildPlayerOptions.target = BuildTarget.StandaloneWindows;
        buildPlayerOptions.options = BuildOptions.None;

        BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
        BuildSummary summary = report.summary;

        if (summary.result == BuildResult.Succeeded) {
            Debug.Log("Build succeeded: " + summary.totalSize + " bytes");
        }else if (summary.result == BuildResult.Failed) { 
            throw new Exception("Build failed");
        }
    }  
}
           

我们想在命令行中通过

output="..."

的方式指定导出位置与名字。

2.1 Freestyle Project

打开

Jenkins

页面,点击

item

(或

新建item

) ,输入任务名

Unity_Jenkins

,创建一个

Freestyle project

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

确认后,我们进入配置页面。

这里的选项很多,但大部分点击问号,都有详细的解释。如有需求,可以自行勾选参数。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

自此我们有两种方式实现自动化构建,使用

Unity3d插件

batch脚本

这里我们暂时先保存,回到主界面。

2.1.1 使用插件 Unity3d plugin

我们通过

Manage Jenkins > Global Tool Configuration

进入工具配置页面,为插件配置编辑器路径。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

保存并退出,回到主页面,点击名字。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

然后进入配置页面。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

构建步骤选择

Invoke Unity3d Editor

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

这里涉及到Unity的命令行模式,官网已经将的十分详细了,建议不熟悉的朋友仔细研读一下:

CommandLineArguments

输入命令行(位置用自己的就行):

-quit -batchmode -buildTarget Standalone -projectPath "E:\Unity_Jenkins" -logFile "E:\output\log.txt" -executeMethod BatchMode.Build output="E:\output\game.exe"
           

注意 :这里一定要通过

-buildTarget

指定平台,不能依赖代码去切换平台。(具体我们后面再说)

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

保存,找到并点击

Build Now

,耐心等待一下,就可以再指定目录下找到打的包了。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略
Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

失败的朋友,可以先看看控制台输出或输出日志

log.txt

找找原因。(控制台中文乱码问题后面再说)

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

似乎,将路径硬编码进命令行不是一个好的方法,我们可以尝试一下参数化构建,在配置页面勾选

This project is parameterized

。添加参数:

buildTarget - ChoiceParameter
project - StringParameter
log - StringParameter
output - StringParameter
           
Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

在命令行中通过

${PARAMETER_NAME}

来引用我们设置的参数。(至于为什么这么引用,可以参考

This project is parameterized

旁边小问号里面的解释)

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

保存退出,点击

Build with Parameters

就能看到我们设置的参数。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

开始构建

同样能够成功出包。

2.1.2 使用 Batch 命令

我们在使用

Unity3d plugin

的基础上进行修改,我们叉掉使用插件构建的方式,选择使用

Execute Windows batch command

的方式进行构建。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

对批处理脚本不够熟悉的朋友建议找资料恶补一下,下面给出官方文档(可当字典):

windows-commands

我们输入以下Batch命令,通过

%PARAMETER_NAME%

来引用参数中的内容。

set unity="D:\Unity\Editor\Unity.exe"
%unity% -quit -batchmode -buildTarget %buildTarget% -projectPath %project% -logFile %log% -executeMethod BatchMode.Build output=%output%

::获取错误信息
set errorCode=%errorlevel%
echo errorCode=%errorlevel%

::打印log信息
echo type log.txt
type %log%

::如果失败,非正常退出,让Jenkins可以知道
exit %errorCode%
           
Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

同样,保存后,点击构建也能正常出包。

2.2 Pipeline

使用

pipeline

管道,我们需要安装插件 Pipeline,只用勾这一个就行了,其他会依赖下载的。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

下载完后,重启。

我们点击

新建Item

,创建一个

Pipeline

的目录。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

这里我们依旧选择参数化构建,勾选

This project is parameterized

buildTarget - ChoiceParameter
project - StringParameter
log - StringParameter
output - StringParameter
           
Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

我们再往下看,流水线这里,需要我们自己写一下代码。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

如果对

Jenkins流水线语法

不太熟悉的话,强烈推荐一下官方文档,真的十分详细了:pipeline

在开发过程中,也要灵活运用下方的

流水线语法

链接,可以快速生成一段代码。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

这里我们使用

Declarative Pipeline

声明试语法。

pipeline {
    agent any
    environment {
        unity="D:Unity\\Editor\\Unity.exe" 
    }
    stages {
        stage('build') {
            steps {
                bat '''%unity% -quit -batchmode -buildTarget %buildTarget% -projectPath %project% -logFile %log% -executeMethod BatchMode.Build output=%output%
                    set errorCode=%errorlevel%
                    echo exit %errorCode%
                    exit %errorCode%'''
                
            }
        }
        stage('log') {
            steps {
                bat '''echo type log.txt
                    type %log%'''
            }
        }
    }
}
           

其内核还是使用batch命令去控制打包,batch部分都是使用片段生成器自动生成的,十分方便(bat脚本内容较多的话,单独写成文件调用执行会比较好)。

我这里分为了两个阶段(可能并不是很合理),一个

build

阶段,一个是

log

阶段。

保存然后构建,我们就可以看到阶段视图全绿成功。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

3 加入SVN

还记得我们最开始加入的SVN插件吗,现在派上用场了。

我们来到

Manage Jenkins > Configure Systemm

,找到

Subversion

一栏,选择正确SVN版本。

svn1.6及以前的版本,每个子文件都会有

.svn

文件,由于我是svn1.14只能选择最新svn1.8…(希望后续有人维护吧)

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

FreeStyle

我们打开

Unity_Jenkins

的配置目录,找到

源码管理

,这里我们勾选

Subversion

,填入相关信息。

Credentials

这里可以输入你的svn账号密码创建凭证。

Check-out Strategy

这里保存svn拉取策略,我们这里默认

Use svn update as much as possible

不清楚的地方可点击蓝色小问号,有着详细的说明。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

有了svn后,Jenkins每次构建时,会从源码库中拉取代码到自己的工作目录中去。

例如,我的Jenkins工作目录在

E:\JenkinsProject\workspace

。我们来到此目录下,可以看到经过之前的一番操作,Jenkins已经为我们的两个任务

Unity_Jenkins

Unity_Jenkins_Pipeline

创建了工作目录,以

@tmp

结尾是临时文件(当然现在它们都是空文件)。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

所以,我们的项目路径不再是

E:\Unity_Jenkins

,而是

E:\JenkinsProject\workspace\Unity_Jenkins

,命令行的项目路也得对应做出修改。此处,我们以Batch命令的版本为例。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

我们可以点击

可用的环境变量

,可以直接用

WORKSPACE

获取工作目录。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

我们删去参数化构建中的

project

参数。

修改batch脚本为

set unity="D:\Unity\Editor\Unity.exe"
%unity% -quit -batchmode -buildTarget %buildTarget% -projectPath %WORKSPACE% -logFile %log% -executeMethod BatchMode.Build output=%output%

::获取错误信息
set errorCode=%errorlevel%
echo errorCode=%errorlevel%

::打印log信息
echo type log.txt
type %log%

::如果失败,非正常退出,让Jenkins可以知道
exit %errorCode%
           

保存,退出即可正常构建。

Pipeline

切换到

Unity_Jenkins_Pipeline

任务,我们直接进入

流水线语法

,在片段生成器中找到步骤

checkout

,填写相关信息,点击

生成流水线脚本

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

复制拉磨一大堆东西,到我们脚本中去。

为了图方便,这里我直接把它放在了

build

阶段中的开头。

同时,还要修改项目路径为

%WORKSPACE%

pipeline {
    agent any
    environment {
        unity="D:Unity\\Editor\\Unity.exe" 
    }
    stages {
        stage('build') {
            steps {
                checkout([$class: 'SubversionSCM', additionalCredentials: [], excludedCommitMessages: '', excludedRegions: '', excludedRevprop: '', excludedUsers: '', filterChangelog: false, ignoreDirPropChanges: false, includedRegions: '', locations: [[cancelProcessOnExternalsFail: true, credentialsId: '', depthOption: 'infinity', ignoreExternalsOption: true, local: '.', remote: 'file:///E:/SVNRepo']], quietOperation: true, workspaceUpdater: [$class: 'UpdateUpdater']])
                
                bat '''%unity% -quit -batchmode -buildTarget %buildTarget% -projectPath %WORKSPACE% -logFile %log% -executeMethod BatchMode.Build output=%output%
                    set errorCode=%errorlevel%
                    echo exit %errorCode%
                    exit %errorCode%'''
                
            }
        }
        stage('log') {
            steps {
                bat '''echo type log.txt
                    type %log%'''
            }
        }
    }
}

           

保存,构建,成功!

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

在实际应用中,我不太喜欢使用

checkout

这种方式去更新项目到Workspace。每次svn被锁,他都会清空工作空间,重新拉取,项目不大还行,项目大了实在是太费时间了。

我更加习惯使用

withCredentials:Bind credentials to variables

,去获取权限,然后自己控制更新位置和节奏。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略
withCredentials([usernamePassword(credentialsId: '你的svn凭证', passwordVariable: '', usernameVariable: '')]) {
    bat '''
    	cd /d %你的项目路径%
    	svn up
    '''
}
           

4 简单的用户管理

安装插件: Role-based Authorization Strategy

安装重启后,我们来到

Manage Jenkins > Configure Global Security

,选择授权策略为

Role-Based Strategy

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

保存,来到

Manage Jenkins > Manage User

,点击

新建用户

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

创建成功后,我们来到

Manage Jenkins > Manage and Assign Roles

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

我们先进入

Manage Roles

分组。

这里我们创建了一个

client

分组,权限开通

read

,剩余的暂时不管,具体的权限在

item roles

中分配。

item roles

中我们让

client

分组的用户只能看见

_Pipeline

结尾的任务,并能对其进行构建

build

,取消构建

Cancel build

,能查看任务信息

Read

,能够更新构建描述

update

如果不清楚某个权限的含义,可以将鼠标悬停在字段上方,会有解释弹出~

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

保存,退出,我们进入

Assign Roles

这里我们将用户

abc

划入

client

分组。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

保存退出,注销登录,我们登上

abc

的账号。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

这里只能看到

Unity_Jenkins_Pipeline

任务,并能对其进行正常构建!

5 细节与坑

说多了都是泪啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊…

5.1 控制台中文乱码

如果你做到这里,实际上应该发现了Jenkins的控制台中已经出现了乱码。

为了试验,我们将在代码

BatchMode.cs

中加入一句中文打印语句,然后

SVN Commite

构建完成后,查看控制台,它乱码了。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

我们可以查看一下Unity的log文件

log.txt

的编码格式,不出意外应该是

UTF-8

这里我们可以来到Jenkins页面,进入

Manage Jenkins > System Information

,这里可以看到系统属性和环境变量。我们主要以下两个值:

file.encoding	    GBK
sun.jnu.encoding	GBK
           

file.encoding

sun.jnu.encoding

这两个是Java的运行时参数,前者影响文件内容编码,后者文件名编码。

说来惭愧,我甚至没找到官方解释。这里给出一些不错的解释文章:

java运行时参数file.encoding和sun.jnu.encoding详解

What exactly is sun.jnu.encoding?

所以接下来目标很明显,我们要把

GBK

改为

UTF-8

。下面的链接里面,大家讨论了如何修改这几个系统变量。

Setting the default Java character encoding

由于我们需要永久性地改变,这里选择使用环境变量的做法。我们新建环境变量

JAVA_TOOL_OPTIONS

,把两个值设置为

UTF-8

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略
-Dfile.encoding=utf-8 -Dsun.jnu.encoding=utf-8
           

JAVA_TOOL_OPTIONIS

这个变量名来自:tooloptions

-Dproperty=value

前缀来自:java Dproperty

设置好后,接下来,我们重启Jenkins。然后再次来到

Manage Jenkins > System Information

,查看这两个值。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略
Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

它们已经成功修改了,我们再构建了一次。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

可以看到代码输出的中文已经正常。

但…

如果你曾在batch脚本中打印一些中文提示的话,似乎。。。乱码变得更多了。例如我这里使用

copy /?

显示一下帮助提示。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

天呐撸!这是因为这部分中文内容是由系统发送给我们的,我们在

cmd

中输入

chcp

指令,可以看到编码格式为GBK。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略
两种常用的编码: 
936 GBK  
65001 utf-8
           

所以接下来就来修改CMD编码格式,我们

Win + R

呼出运行,输入

regedit

打开注册表。

找到

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor

,我们新建一个字符串项。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

然后重命名为

autorun

,修改值为

chcp 65001>nul

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

其原理是每次运行cmd前,会提前执行

chcp 65001

切换编码为

UTF-8

>nul

将输出定位到空,也就不必每次启动cmd都看到切换编码的运行结果了。

我们再次启动cmd查看编码,已经成功切换为

UTF-8

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

但也有缺点,

cmd

给出的执行提示将不再是中文…学好嘤语还是很重要的。

我们再次回到Jenkins,再次执行构建,查看控制台输出,已经没有乱码了。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

5.2 Jenkins 会定时清空工作目录

这将会是一个长达一个月的定时炸弹!

如果你习惯将工程放置于Jenkins 的 workspace下面,当你以为一切稳妥的时候,在未来某一天你会发现workspace下已经空空如也(如果你没有备份,或者使用git/svn,这将是一个致命的问题)

关键问题在于

WorkspaceCleanupThread.java

这个文件:WorkspaceCleanupThread.java

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

它默认了每30天清理一次workspace,如果这不是你期望的,通过设置环境变量来禁止工作目录的清理。

JAVA_TOOL_OPTIONS

中加入以下语句即可。

-Dhudson.model.WorkspaceCleanupThread.disabled=true
           
Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

重启Jenkins,来到

Manage Jenkins > System Information

,确实成功改变即可。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

5.3 EditorUserBuildSettings.SwitchActiveBuildTarget 不可再命令行下使用

这也许是大家比较容易遗忘的点,如果你在BatchMode下依赖

EditorUserBuildSettings.SwitchActiveBuildTarget

来转换平台打包是容易出错的。下面附上原文:

Note: This method is not available when running the Editor in batch mode. This is because changing the build target requires recompiling script code for the given target which cannot be done while script code is executing (not a problem in in the editor as the operation is simply deferred but batch mode will immediately exit after having executed the designated script code). To set the build target to use in batch mode, use the buildTarget command-line switch.

https://docs.unity3d.com/ScriptReference/EditorUserBuildSettings.SwitchActiveBuildTarget.html

这里比较有代表性的问题就是,如果你用这个API刚从其他平台转换到Android平台,宏定义

UNITY_ANDROID

将会失效!

这就会导致有些插件会莫名其妙报错…

老老实实在命令行中使用

-buildTarget

转换平台吧。

5.4 Unity Android 出包失败

在解决这个问题之前,一定要确认在不使用Jenkins的情况下,Unity能够正常打出APK包!!!

此处主要说明由Jenkins导致的失败(请先看5.3!也可能导致失败)。

这里出错的主要原因应该是这个:

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

你当时安装时,为了方便选择了把服务安装到了

LocalSystem

,这直接导致Unity打包时一系列的注册表中的信息获取失败!

再贴一遍官方安装步骤,里面写了选第二个失败的处理方法。

除了重装这一方案,我们来看看其他解决方法。

先说结论,需要我们在

Manage Jenkins > Configure System

中手动设置全局属性

ANDROID_NDK_ROOT

ANDROID_SDK_ROOT

GRADLE_USER_HOME

JAVA_HOME

(如果已经在windows上设置过,可不用再次设置)。

Unity Jenkins SVN 基础全攻略Unity Jenkins SVN 基础全攻略

JAVA_HOME

配java环境的时候应该都配上了,我的是

C:\Program Files\Java\jdk1.8.0_291

保存,构建,就应该没问题了。

接下来说说原理。

你可以试一下,在构建脚本

BatchMode.cs

下,添加以下代码:

Debug.Log("NDK :" + UnityEditor.Android.AndroidExternalToolsSettings.ndkRootPath);
Debug.Log("JDK :" + UnityEditor.Android.AndroidExternalToolsSettings.jdkRootPath);
Debug.Log("SDK :" + UnityEditor.Android.AndroidExternalToolsSettings.sdkRootPath);
           

用Jenkins运行,打印出来的值应该不是你设定的值。

因为,正常来说Unity会在注册表

计算机\HKEY_CURRENT_USER\SOFTWARE\Unity Technologies\Unity Editor 5.x

中获取这些路径的值。

而在Jenkins下运行的Unity会在注册表

计算机\HKEY_USERS\.DEFAULT\Software\Unity Technologies\Unity Editor 5.x

中获取设置对应的值,那么自然就找不了。

想找解决方法,最好好好研究一下Unity编辑器下的一个程序集:

D:\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\UnityEditor.Android.Extensions.dll

可以通过dnSpy反编译一下,重点关注一下:

  • AndroidRoot.cs

    以及它的一系列子类,这里说明了当

    UseEmbedded

    值为

    false

    ,且

    NDK

    SDK

    JDK

    获取失败时,会在环境变量

    ANDROID_NDK_ROOT

    ANDROID_SDK_ROOT

    JAVA_HOME

    中寻找。
  • PostProcessAndroidPlayer.cs

    ,这里写明了打包APK的流程,以及在打包前检查NDK、SDK、JDK失败时,会将

    UseEmbedded

    的值置

    false

    ,并再次获取对应的值(就会再环境变量中找)。

所以,我们在环境变量中设置对应的值能成功build。

然后,再来说说

GRADLE_USER_HOME

,这个环境变量本来不用设置的,它默认是

$USER_HOME/.gradle

详情请见:The Directories and Files Gradle Uses 和 Environment variables

但正常的

.gradle

应该生成在

C:\Users\用户名\.gradle

,Jenkins却生成在了

C:\Windows\System32\config\systemprofile\.gradle

总的来说,装错服务对象,导致User信息完全找不到了(还得是重装比较舒服)。

6 插件推荐与开发建议

废话少说,直接开始:

  • Build Name and Description Setter 可以在build信息处,手动显示更多描述信息
  • build user vars 可以获取当前构建的用户名
  • Extra Columns 视图可编辑

插件开发参考:

  • 官方教程
  • Jenkins API
  • Jelly API
  • 上不了的 Wiki Jenkins

(`・ω・´) 水平有限,如有错,请指正~