2.Unity3D端代码要在Unity中开发
3.Android和Unity3D端,两边都需要加入一些代码从而可以使之关联交互。
4.将Android端代码编译成jar文件以插件形式放入到Unity端中
5.在Unity中将整个项目Build成apk文件,然后安装到手机或模拟器里运行
本文主要讲解1,2,3。对于4,5建议大家去看雨松MOMO的Unity博客的第17篇和第18篇。
UnityPlay:
在编写Android端和Unity3d端代码前,有必要先了解一下可以使两部分交互的类UnityPlay。
个人理解UnityPlay是个Unity提供给外部交互的一个接口类。
为什么是“个人理解”?这我不得不爆粗口了,TMD官网根本就没有相关的API和文档(如果大家有谁找到一定给我来一份,就当我骂自己了)。
在关联Android时,想拿到UnityPlay以及相关类的jar包可以从下面的地址找到:Unity安装路径\Editor\Data\PlaybackEngines\androidplayer\bin在bin文件夹下有一个classes.jar的jar文件,它就是我们想要的。
而在bin同目录下有一个src文件,点击到最后有3个类,分别是UnityPlayerActivity.java,UnityPlayerProxyActivity.java,UnityPlayerNativeActivity.java。前两个打开个后只有一行代码,说的是UnityPlayerActivity和UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity。而打开UnityPlayerNativeActivity中居然有代码,而且我估计这应该是UnityPlayerNativeActivity的源码。
由于关于UnityPlay的资料我只找到这么一个,所以我把UnityPlayerNativeActivity中的代码都贴出来,如果我注解有不对的地方希望大家指正。
/**
* UnityPlayerActivity,UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity
* 而UnityPlayerNativeActivity继承自NativeActivity
* 在该类里定义了一些和ANDROID生命周期相同的回调方法,留给自定义的Activity子类重写。
*/
public class UnityPlayerNativeActivity extends NativeActivity
{
//UnityPlayer的引用,并且我们不能改变这个引用变量的名字,它被native code所引用
protected UnityPlayer mUnityPlayer
protected void onCreate (Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE)
super.onCreate(savedInstanceState)
// 设置显示窗口参数
getWindow().takeSurface(null)
setTheme(android.R.style.Theme_NoTitleBar_Fullscreen)
getWindow().setFormat(PixelFormat.RGB_565)
// 创建一个UnityPlayer对象,并赋值给全局的引用变量
mUnityPlayer = new UnityPlayer(this)
//为UnityPlayer设置一些参数
if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN)
int glesMode = mUnityPlayer.getSettings().getInt("gles_mode", 1)
boolean trueColor8888 = false
// UnityPlayer.init()方法需要在将view附加到layout之前调用。它将会调用native code
mUnityPlayer.init(glesMode, trueColor8888)
// 从UnityPlayer中获取到Unity的View视图
View playerView = mUnityPlayer.getView()
// 将Unity视图加载到根视图上
setContentView(playerView)
// 使Unity视图获取焦点
playerView.requestFocus()
}
protected void onDestroy ()
{
// 当Activity结束的时候调用UnityPlayer.quit()方法,它会卸载之前调用的native code
mUnityPlayer.quit()
super.onDestroy()
}
// 下面几个方法都是ANDROID相关回调方法,确保在ANDROID执行相应方法时UnityPlayer也需调用相应方法
protected void onPause()
{
super.onPause()
mUnityPlayer.pause()
}
protected void onResume()
{
super.onResume()
mUnityPlayer.resume()
}
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig)
mUnityPlayer.configurationChanged(newConfig)
}
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus)
mUnityPlayer.windowFocusChanged(hasFocus)
}
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event)
return super.dispatchKeyEvent(event)
}
}
看完这个类后就知道了为什么在自定义的Activity中继承了UnityPlayerActivity等类以后,只要重写了onCreate并调用super.onCreate()方法后不需要任何其他的代码就会自动的显示出Unity3D的视图。因为初始化Unity视图的代码都在UnityPlayerNativeActivity父类中实现了。
ANDROID端代码:
在写ANDROID代码的时候,一定要导入Unity3D提供给我们的jar包,jar包的位置我在上面说了。引入jar包加入到buildpath中这些最基本的我就不多说了。
要想和Unity交互,我们就不能继承ANDROID提供给我们的Activity,我们需要继承刚才jar包中引入的Unity提供的Activity类,一共有这么3个:
UnityPlayerActivity,UnityPlayerProxyActivity,UnityPlayerNativeActivity。具体区别不知道,因为没有文档,没有API,没有源码(这里再次鄙视一下)。刚才我们看过UnityPlayerNativeActivity的代码(虽然很短,但我觉得这个就是源码),知道UnityPlayerActivity,UnityPlayerProxyActivity都是它的子类,而且最终父类为NativeActivity。所以我们继承Unity提供的最外层的子类是最好的选择,我这里选择的是UnityPlayerActivity,因为名字最简单,觉得该封装的都应该封装好了。
public class MainActivity extends UnityPlayerActivity {
private Button topButton
private Button bottomButton
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
// 设置test为我们的根布局
setContentView(R.layout.test)
// 通过刚才的源码分析,知道mUnityPlayer为一个全局的引用变量,而且已经在父类中设置好了,所以直接拿来用就可以了
View playerView = mUnityPlayer.getView()
// 将Unity的视图添加到我们为其准备的父容器中
LinearLayout ll = (LinearLayout) findViewById(R.id.unityViewLyaout)
ll.addView(playerView)
// 上面的button设置监听器
topButton = (Button) findViewById(R.id.topButton)
topButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//发送消息给Unity端,该函数第一个参数为接受消息的类对象,第二个该类对象用接受消息的方法,第三个参数为传递的消息
//所以下面的意思就为:调用Main Camera下面的Previous方法,传送的消息为空
UnityPlayer.UnitySendMessage("Main Camera","Previous","")
}
})
// 为下面的button设置监听器
bottomButton = (Button) findViewById(R.id.bottomBtn)
bottomButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//调用Main Camera下面的Next方法,传送的消息为空
UnityPlayer.UnitySendMessage("Main Camera","Next","")
}
})
}
}
最后看一下Android端的布局文件,布局很简单,上下各有一个button按钮,两个按钮中间是Unity的视图。
很多项目都会遇到内购和订阅相关模块,这里我总结一下内购接入的时候遇到的各种坑,以及内购测试的时候,有什么比较好的方法测试。本篇先介绍Android篇。
打开Unity编辑器,找到Servic,启用IAP 服务。(启动后也会默认打开数据分析服务)
IAP设置页面,需要设置app适用年龄,根据自己产品自行选择年龄是否13+,然后需要去注意有个Options选项,需要填入一个Google Public Key,这个Key在Google后台,关联产品后就有了,会自动填写上。
接下来就是IAP文档的内容了,建议去官网看文档,这里我把基本框架写出来。
参考: https://docs.unity3d.com/cn/current/Manual/UnityIAP.html
首先创建一个IAPManager
初始化IAP,并且创建好所有内购产品(提前在后台生成ProduceID)
创建IAPItem时候,传入产品ID和产品类型要与后台一致。
初始化成功:
初始化失败:
购买产品,传入对应产品ID:
购买成功:
购买失败:
这几个方法,一定打好log,这里就是核心的几个内购方法,另外当接入google结算库时候,要引入Google.Play.Billing时候,编辑器可能报错找不到。
在Player Settings ->Other Settings 添加宏定义:
1.Android运行环境的搭建
进行安卓系统的软件设计,那么JDK的开发环境搭建必须是首要的。我们选择Windows10 64位 *** 作系统。同时在JDK版本的选择中选用Windows x64版本的Java SE Development Kit 8u5,该版本稳定,应用广泛而且开源免费,获取方便。在安装的过程中要注意不要重复安装,应安装完毕后立即删除安装包,否则如果不小心再次点到安装包,该安装包会立刻删除所安装的程序并询问是否重新安装。在JDK的安装过程中,要注意开发工具,源代码,公共JRE三项都要选中,而且要安装到C盘默认目录下,同时将其附带的JRE同样安装到相同目录下,同时硬盘至少应该留有2G的空间。
选择好JDK的版本并进行安装后,我们的JAVA环境就安装好了,众所周知,安卓系统是由JAVA语言架构的,所以在搭建安卓运行环境之前必须要先安装JAVA环境。安装完JAVA环境之后,我们进行安卓开发环境的搭建。我们就要进行Android SDK版本的选择。我们这里选择android-sdk_r24.4.1-windows版本。这个版本是与安卓8.0同时发布的,同时它的发布时间也在我们的安卓测试机红米NOTE5A型号之后,可以完美兼容我们的安卓测试机所运行的安卓7.1.2版本。
图1 Android运行环境的搭建
Fig.1 Setup of the Android operating environment
2. Windows10系统环境变量的配置
环境变量是在 *** 作系统中的一个对象,该对象具有特定的名字,用来指定 *** 作系统在运行时的一些参数。在电脑属性的高级系统属性中进行环境变量的编辑。首先新增两个系统变量,变量名称分别为%JAVA_HOME%和%ANDROID_HOME%,变量值分别为各自安装目录。然后修改系统变量中的PATH变量,我们这里采用的是Windows10系统,修改PATH变量相对于Windows7来说更为方便快捷,在PATH环境变量中新建四条属性,如图2所示。
图2系统环境变量配置
Fig.2 System environment variable configuration
3. SDK的下载与安装
配置完系统的环境变量后进行SDK的下载与安装。上文提到了我们选择的版本为android-sdk_r24.4.1-windows版本,将其下载好的压缩包进行解压缩,然后打开Android SDK安装目录下的SDK MANAGER程序,在TOOLS目录下安装Android SDK Tools 24.4.1、Android SDK Platform-tools 27.0.1、Android SDK Build-tools 27.0.3,系统提示的版本是否升级我们选择否选项,因为该版本与我们相应的JDK8.0以及安卓测试机运行版本都能够相匹配,如果选择更新到最新版本可能会导致一系列因为兼容性或者不匹配性所导致的错误。
API方面选择从API15到API27,即Android4.0.1到Android 8.1.0,API(Application Programming Interface)是应用程序编程接口,其工作原理是是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。在Windows10运行环境下我们自然需要相应的API进行安卓软件的开发。在Extras目录下安装Google Play services和Google USB Driver,Google Play services和IOS系统下的GameCenter的作用是相同的。
当我们打开游戏软件应用时就会出现在主屏上。可以使用谷歌的账号登录,然后创建一个昵称,可以添加一个电子邮件地址,以便与好友联系。当用户登录一个已有的谷歌账号或者注册一个新账号时,载有服务条款的界面即会呈现给用户。此时使用者可新建一个独一无二的游戏账号,而昵称和其他一些信息则用于接收其他玩家向你发出的好友邀请,当然其他游戏玩家也可以通过电子邮件来查找你。除此之外,只需点击该服务中相应的链接即可下载游戏。我们可以使用它玩相应的类似《部落战争》的游戏。
至于Google USB Driver,则使我们的安卓系统开发具有利用USB接口传输数据的能力,可以让我们所开发的软件可以通过USB接口进行相应的输入和输出。USB即插即用、支持热插拔、传输速度快、可通过扩展连接多达127个 USB 设备,不用担心 USB 加密锁与打印机等外设的冲突,极大的提高的我们所开发软件的适应性与传播性。
在相应的Build tools,API,Extras服务都安装完毕后,我们的安卓SDK就可以正常运行了,不过在此之前需检查安装目录下的tools文件夹是否存在zipalign文件,如果不存在的话将会无法运行接下来的步骤。我们需要手动将安装目录下的build-tools文件夹中的相应版本的zipalign文件复制到tools对应文件夹下。从Android 1.6 SDK版本开始,SDK中就包含了一个用于优化APK的新工具zipalign。
它提高了优化后的Applications与Android系统的交互效率,从而可以使整个系统的运行速度有了较大的提升。Android小组强烈建议开发者在发布新Apps之前使 用zipalign优化工具,而且对于已经发布但不受限于系统版本的Apps,建议用优化后的APK替换现有的版本。使用zipalign工具,会提升我们的APP性能,降低内存使用率,降低手机发热程度,这对于我们的由小米手机厂商开发的红米NOTE5A手机来说是“至关重要”的。使用cmd命令符进行zipalign优化如图3所示。
图3 zipalign优化
Fig.3 the optimization of zipalign
4. Android SDK接口的设置及APK的生成
手机屏幕尺寸在主视窗口Game模块下将Free Aspect修改为16:10 LandScape屏幕比例,以适应大部分安卓手机。
SDK与JDK的接口设置:在unity编译器中选择SDK,JDK安装目录进行环境配置,安卓API选择Android5.0版本,并更新项目名称,将SDK版本升级到Sdk18以上。在Build Setting中将设置修改为安卓5.0。
以上就是安卓环境的安装和搭建,更多Unity开发方面的问题可以看下这个视频教程网页链接,希望我的回答能帮到你。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)