游戏开发进阶教你自制离线Maven仓库,实现Unity离线环境使用Gradle打包(Unity | Android | 谷歌 | Gradle)

Posted 林新发

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏开发进阶教你自制离线Maven仓库,实现Unity离线环境使用Gradle打包(Unity | Android | 谷歌 | Gradle)相关的知识,希望对你有一定的参考价值。

一、前言

嗨,大家好,我是新发。
最近在忙的谷歌提审的事情,涉及到UnityGradle打包,感觉有必要写一篇文章讲讲,话不多说,我们开始吧。

特别说明,我的电脑环境如下:
外网机:win10操作系统,Unity版本2019.4.17f1c1
内网机:win7操作系统,Unity版本2017.4.29f1

二、Gradle与android Gradle Plugins

关于GradleAndroid Gradle Plugins,相信刚使用Gradle的小伙伴会傻傻分不清,不要怕,今天我就来给你讲清楚。
在这里插入图片描述

1、Gradle工具

1.1、Gradle工具简介

Gradle是一个项目构建工具,它主要是为了解决项目的自动化构建。Gradle同时也是一个开发框架,它有自己的开发语言Groovy, 我们可以通过Groovy语言去写自己的Gradle插件,也可以去编写指定的脚本去改变构建规则。
在这里插入图片描述

这样讲或许对于萌新小伙伴还是不大好理解,为什么要自动化构建,我以一名Unity游戏开发工程师的角度来解释一下,实际项目我们可能会打包上架到各大应用市场,比如应用宝、华为、小米、OPPOVIVOGoogle等等,一个工程要打那么多渠道包,每个渠道包集成的SDK不同,还有一些配置、资源差异等等,我们不可能挨个手动修改然后再打包。
还好Unity提供了各种EditorAPI方便开发者自定义打包工具,另外我们还可以通过命令行调用我们自己实现的打包工具,如果再集成jenkins,那么打包各个渠道包就完全可以交给策划的同事来执行了,支持远程自动化批量打包,实在不能太香了。

注:关于打多渠道包这样的需求,市面上也有一些聚合SDK帮开发者做了工具,不过主动权就不在自己这边了,这个具体场景具体分析,实际应用场景可能更加复杂,需求多变,我们可能依然还是需要自己实现打包工具。

在这里插入图片描述

同样的道理,Gradle就是为了实现类似上面我讲的这个需求而生的。
Gradle被设计成支持跨多种语言和平台的构建自动化,包括JavaScalaAndroidC/C++Groovy,所以它并不是Android的专属哦。
如果你访问GradleGitHubhttps://github.com/gradle/gradle
你就可以看到它可以构建各种类型的项目,
在这里插入图片描述

我们看GradleLOGO是一只三条腿的大象,少了一条腿,或许是想告诉开发者:你可以自己定义第四条腿,自由发挥,一方面展现了Gradle的功能的强大,另一方面又表达了它良好的可扩展性和包容性。(纯属个人YY
在这里插入图片描述

1.2、Gradle工具下载

Gradle工具各个发行版本可以从这里下载:https://services.gradle.org/distributions/
在这里插入图片描述
从上面我们可以看到Gradle的迭代更新是非常快的,它是开源的,社区非常活跃。
这是GradleGithub地址:https://github.com/gradle/gradle
感兴趣的同学可以下载下来学习它的源码。
在这里插入图片描述

1.3、在Android Studio中配置Gradle工具

如果你用过Android Studio,那么你肯定对Gradle不陌生,我们在gradle-wrapper.properties中配置的distributionUrl就是Gradle工具的下载路径,
在这里插入图片描述
在这里插入图片描述
我们也可以先把Gradle的某个版本下载到本地,然后把distributionUrl改成本地路径,例:
在这里插入图片描述
画成图是这样子:
在这里插入图片描述
需要注意,上面我说的的gradle-wrapper.properties其实是Gradle Wrapper的配置。
嗯?Gradle Wrapper是啥?与Gradle又是什么关系?
Gradle WrapperGradle的又一层封装,正如上面你看到Gradle有很多个版本,不同项目可能使用不同的Gradle版本来构建,所以就又封装了个Gradle Wrapper,方便不同项目配置不同版本的Gradle,嘛,再画个图吧~
在这里插入图片描述
我们在Android项目的gradle/wrapper目录中可以看到gradle-wrapper.jar,它就是Gradle Wrapper本君啦~
在这里插入图片描述
Gradle Wrapper干的主要事情就是下载安装Gradle,你可以用jd-gui反编译一下gradle-wrapper.jar,如下:

注:jd-guijava的反编译工具,直接把.jar文件拖到jd-gui中即可看到java代码了。
jd-gui下载地址:https://jd-gui.apponic.com/

在这里插入图片描述

1.4、在Unity中配置Gradle工具

现在,我们对应回Unity,我以2019.4.17f1c1版本为例,点击菜单Edit / Preferences...
在这里插入图片描述
打开Preferences窗口,点击External Tools按钮,即可看到Gradle的路径配置,
在这里插入图片描述
这与上面我们讲的在Android Studiogradle-wrapper.properties中配置本地Gradle是一样的道理。
其实Unity自身集成一个Gradle工具,在Unity的安装目录中,
路径:Unity安装目录\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Tools\\gradle\\lib
我们进到该目录就可以看到Gradle工具本君啦,
在这里插入图片描述
我们也可以自行去这里 https://services.gradle.org/distributions/ 下载其他版本的Gradle,然后在UnityPreferences窗口中设置为本地的其他版本的Gradle的路径。
为了方便大家理解,我再画个图,
在这里插入图片描述
另外,如果你的Unity版本是2018或以下版本,在Preferences窗口中就没有Gradle路径的设置了,我以Unity2017为例,如下
在这里插入图片描述
但不代表Unity没有内置Gradle,早在Unity5.x版本就已经内置了Gradle了,我们可以进到这个目录:Unity安装目录\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Tools\\gradle\\lib,依然可以看到UnityGradle哦,只是不同版本的Unity内置的Gradle版本不同,
在这里插入图片描述

1.5、在Unity中开启Gradle方式构建项目

Unity2018或以下版本,我们在Build Settings中可以设置Build SystemInternalGradle,以以Unity2017为例,如下
在这里插入图片描述
到了Unity2019就默认只能以Gradle方式构建项目了,
在这里插入图片描述

2、Android Gradle Plugins插件

2.1、Android Gradle Plugins与Gradle的关系

Gradle工具具有强大的可扩展性,我们可以为其写插件来实现特定类型的项目的自动化构建。
为了让Gradle能够更加便捷地构建Android项目,Google团队开发了Android Gradle Plugins插件,注意,Android Gradle PluginsGoogle开发的,不是Gradle团队开发的,不要搞混啦,画个图方便大家记住~
在这里插入图片描述
关于Android Gradle Plugins的更多介绍,可以访问官方文档:
https://developer.android.google.cn/studio/releases/gradle-plugin

在这里插入图片描述

2.2、Android Gradle Plugins手动下载

Android Gradle Plugins在哪里下载呢?
一般是从Googlemaven仓库下载,我们可以在浏览器访问Googlemaven网站:https://mvnrepository.com/
在这里插入图片描述
搜索android gradle plugins即可找到啦,
在这里插入图片描述
点进去可以看到Android Gradle Plugins也有很多个版本,
在这里插入图片描述

2.3、Android Gradle Plugins版本与Gradle版本的对应关系

Gradle有好多个版本,Android Gradle Plugins也有好多个版本,特定版本的Android Gradle Plugins需要对应特定版本的Gradle,否则它们之间可能不能正常协同工作,毕竟,它们是两个开发团队开发的,Gradle在快速迭代,Android Gradle Plugins也在快速迭代,为此,Google专门列出了Android Gradle PluginsGradle的版本对应关系表格:

具体可以参见Google《Android Gradle 插件版本说明》

Android Gradle Plugins插件版本所需的 Gradle 版本
1.0.0 - 1.1.32.2.1 - 2.3
1.2.0 - 1.3.12.2.1 - 2.9
1.5.02.2.1 - 2.13
2.0.0 - 2.1.22.10 - 2.13
2.1.3 - 2.2.32.14.1 - 3.5
2.3.0+3.3+
3.0.0+4.1+
3.1.0+4.4+
3.2.0 - 3.2.14.6+
3.3.0 - 3.3.34.10.1+
3.4.0 - 3.4.35.1.1+
3.5.0 - 3.5.45.4.1+
3.6.0 - 3.6.45.6.4+
4.0.0+6.1.1+
4.1.0+6.5+
4.2.0+6.7.1+
2.4、Android Studio中配置Android Gradle Plugins

上面我们是手动去Googlemaven仓库下载Android Gradle Plugins,这种需要手动下载的操作,在Gradle面前,是不存在滴。
我们以Android Studio为例,打开Projectbuild.gradle文件,
在这里插入图片描述
我们只需要在dependencies中配置一下com.android.tools.build:gradle:版本即可,如下
在这里插入图片描述
细心的同学应该注意到了repositories中默认是google()jcenter(),即优先从GoogleMaven仓库下载依赖库,
在这里插入图片描述
当然,我们可以在前面添加国内的源来提升下载速度,比如改为阿里云的源:

repositories {
    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
    maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
    //google()
    //jcenter()
}

如下:
在这里插入图片描述

2.5、Unity中配置Android Gradle Plugins

对应回Unity项目,我以Unity2017.4.29f1版本为例,在Player Settings中,我们点开Publishing Settings,在里面可以看到有个Custom Gradle Template勾选,我们把它勾选上,
在这里插入图片描述
此时会在Assets/Plugins/Android目录中生成一个mainTemplate.gradle文件,
在这里插入图片描述
它就等价于上面Android Studio中的build.gradle文件,我们打开mainTemplate.gradle文件,可以看到它依赖了3.2.0版本的Android Gradle Plugins,我们可以修改为其他版本,但一般默认即可;另,它也是默认从googlejcenter仓库下载依赖库的,

// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
	repositories {
		google()
		jcenter()
	}

	dependencies {
		classpath 'com.android.tools.build:gradle:3.2.0'
	}
}

allprojects {
   repositories {
      google()
      jcenter()
      flatDir {
        dirs 'libs'
      }
   }
}

apply plugin: 'com.android.application'

dependencies {
	implementation fileTree(dir: 'libs', include: ['*.jar'])
**DEPS**}

android {
	compileSdkVersion **APIVERSION**
	buildToolsVersion '**BUILDTOOLS**'

	defaultConfig {
		minSdkVersion **MINSDKVERSION**
		targetSdkVersion **TARGETSDKVERSION**
		applicationId '**APPLICATIONID**'
		ndk {
            abiFilters **ABIFILTERS**
        }
		versionCode	**VERSIONCODE**
		versionName	'**VERSIONNAME**'
	}

	lintOptions {
		abortOnError false
	}

	aaptOptions {
		noCompress '.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**
	}

**SIGN**
	buildTypes {
  		debug {
 			minifyEnabled **MINIFY_DEBUG**
 			useProguard **PROGUARD_DEBUG**
 			proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD**
  			jniDebuggable true
  		}
  		release {
 			minifyEnabled **MINIFY_RELEASE**
 			useProguard **PROGUARD_RELEASE**
  			proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD**
  			**SIGNCONFIG**
  		}
	}
**PACKAGING_OPTIONS**
    bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = false
        }
        abi {
            enableSplit = true
        }
    }
}

**SOURCE_BUILD_SETUP**

上面的mainTemplate.gradle文件其实是从Unity.gradle模板文件拷贝过来的。
我们可以在Unity安装路径/Editor/Data/PlaybackEngines/AndroidPlayer/Tools/GradleTemplates目录中看到三个.gradle模板文件,如下,我们可以修改这些.gradle模板文件,比如修改它的源改为阿里云之类的。
在这里插入图片描述
如果你是Unity2019,比如以2019.4.17f1c1为例,则会看到Publishing Settings中变成了三个勾选,
在这里插入图片描述
勾选后在Assets/Plugins/Android目录中可以看到对应的gradle文件
在这里插入图片描述
同样,我们在Unity安装路径/Editor/Data/PlaybackEngines/AndroidPlayer/Tools/GradleTemplates目录中可以看到.gradle模板文件,对比Unity2017是略有差异的,
在这里插入图片描述
Android Gradle Plugins的依赖是在baseProjectTemplate.gradle中配置的,如下,可以看到2019.4.17f1c1依赖的Android Gradle Plugins版本为3.6.0

// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

allprojects {
    buildscript {
        repositories {**ARTIFACTORYREPOSITORY**
            google()
            jcenter()
        }

        dependencies {
            // If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity
            // See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html
            // See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
            // To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version
            classpath 'com.android.tools.build:gradle:3.6.0'
            **BUILD_SCRIPT_DEPS**
        }
    }

    repositories {**ARTIFACTORYREPOSITORY**
        google()
        jcenter()
        flatDir {
            dirs "${project(':unityLibrary').projectDir}/libs"
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

三、Unity离线环境下使用Gradle打包的问题

一般实际项目都是在内网开发的,即在离线环境下开发,无法连接网络。而我们上面说到,使用Gradle构建Android项目时,它是依赖Android Gradle Plugins插件的,默认情况下会去googlejcenter仓库下载依赖的库,
在这里插入图片描述
显然,此时你在离线环境打包就会报这样的错:
在这里插入图片描述
事实上,Unity会先帮我们把Unity工程转成Gradle工程,我们可以在工程路径下的Temp/gradleOut中看到生成的Gradle工程,看到那个build.gradle文件了吗,它就是我们上文说的.gradle模板文件生成出来的,
在这里插入图片描述
离线环境无法连接googlejcentermaven仓库,那我们就自己搭建一个离线版的maven仓库吧,画图,
在这里插入图片描述

四、搭建离线maven仓库

1、Google官方离线版maven仓库

Google提供了一个离线版的maven仓库,下载地址:https://developer.android.com/studio#downloads
在这里插入图片描述
我们可以看到这个离线版的maven仓库有2.7G那么大,如果我们只是需要解决Android Gradle Plugins依赖的问题,我们的离线仓库其实只需要Android Gradle Plugins和它依赖的库即可,没必要下载Google这个2.7G的仓库,下面我就来教大家制作一个迷你版的离线仓库。

2、自制迷你版maven仓库

原理:本地仓库是远程仓库的一个缓冲和子集,首先会从本地仓库查找资源,如果没有,则从远程仓库下载到本地仓库,我们就可以利用这个缓冲子集来制作迷你版离线仓库啦。

撸起袖子开干~

Gradlemaven缓冲路径为C:\\Users\\当前用户\\.gradle\\caches,我们在外网环境下(即可以连接网络的电脑上),先看下本地这个路径C:\\Users\\当前用户\\.gradle\\caches,如果caches目录中有文件,先清空它,如果找不到这个cache目录,则直接下一步,
在这里插入图片描述
使用Unity创建一个空工程,使用Gradle方式构建Android项目,此时Gradle会下载依赖的库到这个caches目录中,因为我们清空了caches,所以这次打包时间会比较长,耐心等待。
打包完毕后我们就可以看到这个caches目录中多了一些文件出来啦,这些就是下载下来的缓存文件,
在这里插入图片描述
整个caches文件夹只需要132M
在这里插入图片描述
我们把整个.caches文件夹压缩后传到内网,用于制作离线版maven仓库。
在这里插入图片描述
如下,转到了内网机中,
在这里插入图片描述
解压到当前文件夹,
在这里插入图片描述
解压后进入caches/modules-2/files-2.1目录中,可以看到各个依赖库的文件夹,
在这里插入图片描述
如果你对比过真实的maven仓库文件夹你就会发现,上面这种文件结构是不对的,举个例子,比如com.android.tools.build
在这里插入图片描述
正确的maven仓库路径会拆分成多级目录,即:com/android/tools/build,我们要以.为分割拆分成多级目录。
另外,我们继续进到目录里面,以gradle-3.2.0.jar为例,可以看到它被放在com.android.tools.build\\gradle\\3.2.0\\1851dd6a2badb1a66e5fcafc311073d7ad0b3183这个目录中,
在这里插入图片描述
比正确的maven仓库多了一层1851dd6a2badb1a66e5fcafc311073d7ad0b3183目录,我们需要把gradle-3.2.0.jar放到上层目录中,即最终正确的路径应该为:
com\\android\\tools\\build\\gradle\\3.2.0\\gradle-3.2.0.jar
同理,其他文件也是按照这个路径规则调整,嘛,写个python脚本批量处理一下吧~
caches同级目录中创建一个gen_repository.py脚本,
在这里插入图片描述
gen_repository.py脚本代码如下:

import os
import shutil

def walk_caches(caches_path):
    for root, dirs, fs in os.walk(caches_path):
        for f in fs:
            yield (root, f)
            

if '__main__' == __name__:
    caches_path = 'caches/modules-2/files-2.1/'
    for (root, f) in walk_caches(caches_path):
        dir_tmp = root.replace(caches_path, '')
        module_name = dir_tmp[0:dir_tmp.find('\\\\')]
        module_split_path = module_name.replace('.', '/')
        target_dir = './repository/' + module_split_path + dir_tmp[dir_tmp.find('\\\\'):dir_tmp.rfind('\\\\')]
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)
        target_file_path = os.path.join(target_dir, f)
        if not os.path.exists(target_file_path):
            shutil.copy(os.path.join(root, f), target_file_path)
            print('copy ' + f)
    print('done')

执行一下gen_repository.py脚本,生成了一个repository,我们的离线版迷你仓库就这样制作完成啦,记住它的路径:F:/GoogleMaven/repository,下文需要用到这个路径。
在这里插入图片描述

3、配置本地离线版maven

用过maven的同学应该知道,离线maven仓库默认路径是在C:\\Users\\当前用户\\.m2\\repository,嘛,C盘空间寸土寸金,肯定不要放C盘里。还好maven还提供了一个settings.xml给我们,我们只需要在C:\\Users\\当前用户\\.m2目录中放一个settings.xml并配置具体的repository路径即可,如果你本机没有C:\\Users\\当前用户\\.m2这个目录则手动创建一个,
在这里插入图片描述
settings.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   | Default: ${user.home}/.m2/repository  -->
    <localRepository>F:/GoogleMaven/repository</localRepository>

    <pluginGroups>
        <pluginGroup>org.sonatype.plugins</pluginGroup>
        <pluginGroup>org.mortbay.jetty</pluginGroup>
    </pluginGroups>

    <proxies>
    </proxies>

    <servers>
    </servers>

    <mirrors>
    </mirrors>

    <profiles>
    </profiles>

    <activeProfiles>
    </activeProfiles>
</settings>

最重要的就是这句:

<localRepository>F:/GoogleMaven/repository</localRepository>

接着,修改一下Unity安装路径下的的.gradle模板文件的仓库为本地仓库(mavenLocal),
在这里插入图片描述
如下:
在这里插入图片描述
在这里插入图片描述
Unity中勾选Custom Gradle Template
在这里插入图片描述
此时就会从Unity安装路径下拷贝.gradle模板文件到工程路径中Assets/Plugins/Android
在这里插入图片描述
如果你之前拷贝了旧的gradle模板文件,则记得把工程中的.gradle文件的仓库也改成本地仓库(mavenLocal),如下
在这里插入图片描述
画个图方便大家理解,
在这里插入图片描述

4、Unity使用Gradle打包测试

Build Settings中设置Build SystemGradle

注:如果你是Unity2019或以上版本,则默认是使用Gradle来构建Android,不需要设置Build System

在这里插入图片描述
执行Build打包,打包成功,
在这里插入图片描述
成功生成apk,如下
在这里插入图片描述

五、完毕

好了,就先写这么多吧,另外再啰嗦一下,今年很多项目会选择出海,上架Google需要使用AAB格式,必须使用Gradle方式打包,同时必须支持x64架构,所以必须使用IL2CPP编译才能发布x64架构的应用,预祝大家出海成功,我是新发,喜欢我的文章的可以点点关注,有任何疑问的可以留言或私信,能帮上的我都会尽量解答,好了,肚子饿了,我要去吃午饭了,拜拜~

以上是关于游戏开发进阶教你自制离线Maven仓库,实现Unity离线环境使用Gradle打包(Unity | Android | 谷歌 | Gradle)的主要内容,如果未能解决你的问题,请参考以下文章

跨平台应用开发进阶(二十九) :uni-app 实现Android原生APP-云打包集成神策详细教程

游戏开发进阶教你Unity通过Jenkins实现自动化打包,打包这种事情就交给策划了(保姆级教程 | 命令行打包 | 自动构建)

游戏开发进阶教你Unity通过Jenkins实现自动化打包,打包这种事情就交给策划了(保姆级教程 | 命令行打包 | 自动构建)

跨平台应用开发进阶(四十)自定义插件及引用

跨平台应用开发进阶(四十)自定义插件及引用

教你用 Python 自制简单版《我的世界》