位置: 编程技术 - 正文

Unity3D游戏开发之在Android视图中嵌入Unity视图(Unity3D游戏开发标准教程)

编辑:rootadmin

推荐整理分享Unity3D游戏开发之在Android视图中嵌入Unity视图(Unity3D游戏开发标准教程),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:Unity3D游戏开发基础,Unity3D游戏开发(第2版),Unity3D游戏开发引擎,Unity3D游戏开发标准教程,Unity3D游戏开发标准教程,Unity3D游戏开发毕业论文,Unity3D游戏开发标准教程,unity3D游戏开发,内容如对您有帮助,希望把文章链接给更多的朋友!

转载自: 今天我们继续来研究Unity在Android平台上的扩展,通过昨天的学习,大家已经知道Unity和Android是可以互相调用的,可是相信大家从昨天的文章中可以看出,如果单纯地从调用Android接口的角度来看,我们已经可以实现这一目的。可是从实际开发的角度来看,我们只是迈出了很小的一步。为什么这么说呢,因为在实际的开发中可能我们不仅需要从接口上实现与Unity的对接,而且需要从界面上实现与Unity的对接。比如,现在主流的网游都会在游戏开始的时候给玩家一个选择创建角色的过程,通常界面上会显示各种类型的角色设定,玩家可以通过界面了解每种类型的角色的特点,从而选择合适自己的角色。从技术上来讲,这一部分我们可以完全使用Unity3D的GUI系统来实现,不过本文的目的在于探讨Unity和Android的对接问题,因此我们可以假定Android在整个对接过程中扮演着界面渲染的角色,而Unity则负责游戏逻辑的维护。那么,这样就诞生了我们今天的问题,能不能将Unity作为Android界面的一部分嵌入到Android应用中呢?答案当然是肯定的。

一、为Unity编写Android插件

首先,我们来看Unity中为Android提供的类文件UnityPlayerNativeActivity.java,该文件位于如下位置:

D:ProgramFilesUnityEditorDataPlaybackEnginesandroidplayercomunity3dplayer(在不同的计算机上可能会有所不同,大家灵活运用即可)

[java] view plaincopyprint?package com.unity3d.player; import android.app.NativeActivity; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.os.Bundle; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; public class UnityPlayerNativeActivity extends NativeActivity { protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code // Setup activity layout @Override 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_); mUnityPlayer = new UnityPlayer(this); if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true)) getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(mUnityPlayer); mUnityPlayer.requestFocus(); } // Quit Unity @Override protected void onDestroy () { mUnityPlayer.quit(); super.onDestroy(); } // Pause Unity @Override protected void onPause() { super.onPause(); mUnityPlayer.pause(); } // Resume Unity @Override protected void onResume() { super.onResume(); mUnityPlayer.resume(); } // This ensures the layout will be correct. @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mUnityPlayer.configurationChanged(newConfig); } // Notify Unity of the focus change. @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); mUnityPlayer.windowFocusChanged(hasFocus); } // For some reason the multiple keyevent type is not supported by the ndk. // Force event injection by overriding dispatchKeyEvent(). @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_MULTIPLE) return mUnityPlayer.injectEvent(event); return super.dispatchKeyEvent(event); } // Pass any events not handled by (unfocused) views straight to UnityPlayer @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } /*API*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } } 熟悉Android开发的朋友一定对这个类觉得&#;熟吧,NativeActivity是Google在Android3.0后推出的,其目的是为了让开发者使用C/C&#;&#;在NDK环境下管理Activity的生存周期,于是我们可以大胆的猜测Unity之所以可以和Android进行交互是因为NDK提供了方便之门,果然,博主在Unity的目录下找到了libmain.so、libunity.so、libmono.so这三个文件,这证实我们的猜想是正确的。在这个类中,我们可以看到Unity做了大量的初始化工作,并且重写了NativeActvity的相关方法。不知道大家还记不记得我们在前一篇文章中定义主Activity时,我们是让它继承自UnityPlayerActivity而不是Android的Activity。那么,这个UnityPlayerActivity是什么呢?我们打开它的文件:

[java] view plaincopyprint?package com.unity3d.player; /** * @deprecated Use UnityPlayerNativeActivity instead. */ public class UnityPlayerActivity extends UnityPlayerNativeActivity { } 这时候我相信大家和博主一样都有一种恍然大悟的感觉,原来它是继承自UnityPlayerNativeActivity的,换句话说Unity在Android这部分其实做了两件事,即初始化Activity和重写相关的方法。我们注意到代码中的注释提示这个类已经deprecated建议我们使用UnityPlayerNativeActivity,这点我们暂时不用管,我们依然使用UnityPlayerActivity,因为它和UnityPlayerNativeActivity本质上是一样的。好了,到目前为止,如果大家已经理解了这里所有的内容,那么我们可以浩浩荡荡地冲向Eclipse开始编写Android项目了。

和昨天一样,我们创建一个Android项目并将其设为库,这里我们将其包名设为com.android.unityview4android。这个名称很重要,我们在Unity中将继续使用这个名字。首先我们来创建一个Android的布局文件activity_main.xml:

Unity3D游戏开发之在Android视图中嵌入Unity视图(Unity3D游戏开发标准教程)

[html] view plaincopyprint?<RelativeLayout xmlns:android=" xmlns:tools=" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <Button android:id="@&#;id/BtnPre" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="@string/BtnPre" /> <LinearLayout android:id="@&#;id/UnityView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@&#;id/BtnNext" android:layout_below="@&#;id/BtnPre" android:orientation="vertical" > </LinearLayout> <Button android:id="@&#;id/BtnNext" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="@string/BtnNext" /> </RelativeLayout>

这里我们放置了两个Button按钮,分别用来控制Unity向前、向后切换模型,在屏幕中间有一个叫做UnityView的线性布局,它将作为Unity视图的父控件,即我们会将Unity的视图放到这个控件里。我们注意到在UnityPlayerNativeActivity.java类中有一个UnityPlayer类型的变量mUnityPlayer,该类型博主目前没有找到官方的相关说明,博主推测它应该是负责Unity界面渲染的一个类吧,在这个类中有一个getView()方法,它将返回一个View类型的&#;,我们便可以通过这种方法将其添加到Android视图里,因为我们已经准备好了一个UnityView的父控件,所以这一切实现起来变得相当地容易:

[java] view plaincopyprint?package com.android.unityview4android; /*导入Unity提供的类*/ import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; public class MainActivity extends UnityPlayerActivity { private Button BtnPre,BtnNext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置当前布局文件 setContentView(R.layout.activity_main); //获取显示Unity视图的父控件 LinearLayout mParent=(LinearLayout)findViewById(R.id.UnityView); //获取Unity视图 View mView=mUnityPlayer.getView(); //将Unity视图添加到Android视图中 mParent.addView(mView); //上一个 BtnPre=(Button)findViewById(R.id.BtnPre); BtnPre.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { UnityPlayer.UnitySendMessage("GameObject", "ShowPrevious", ""); } }); //下一个 BtnNext=(Button)findViewById(R.id.BtnNext); BtnNext.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { UnityPlayer.UnitySendMessage("GameObject", "ShowNext", ""); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } 好了,这样我们就完成了Jar库的编写,我们只要将Jar库导入到Unity中,并且按照上一篇文章中所述的方法构建Android插件目录组织相关资源就可以了。最后我们给出AndroidManifest.xml文件:[html] view plaincopyprint?<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" package="com.android.unityview4android" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.android.unityview4android.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

二、创建Unity项目 好了,现在我们来创建Unity项目,我们这里创建一个简单地场景,场景中只有一个空游戏体和摄像机,我们将通过脚本的形式来控制Unity渲染,主要的脚本代码如下:

[csharp] view plaincopyprint?using UnityEngine; using System.Collections; public class ModelManager : MonoBehaviour { //模型 public GameObject[] Models; //当前索引 private int index=0; //当前对象 private GameObject mObject; void Start () { this.name="GameObject"; //生成第一个物体 mObject=(GameObject)Instantiate(Models[index]); } public void ShowNext() { //使索引增加 index&#;=1; //范围控制 if(index>Models.Length-1){ index=0; } //销毁原来物体 Destroy(mObject); //生成新物体 mObject=(GameObject)Instantiate(Models[index]); } public void ShowPrevious() { //使索引减少 index-=1; //范围控制 if(index<0){ index=Models.Length-1; } //销毁原来物体 Destroy(mObject); //生成新物体 mObject=(GameObject)Instantiate(Models[index]); } } 这段脚本我们绑定到这个空的游戏体上,脚本的两个方法ShowNext()和ShowPrevious()相对应,通过UnitySendMessage()实现通信。好了,我们来运行项目,如图所示:

我们可以注意到当程序打开的那一瞬间,是Android视图先加载、然后Unity视图才加载的,给人整体的感觉就是在Activity里面嵌套了一个Activity。可是博主马上就发现了一个问题,这Android视图中的按钮无法取得焦点啊,点击事件无效。这是为什么呢?后来博主找到的解决方法是在AndroidManifest.xml文件中的activity子节点下增加如下两行代码:

[csharp] view plaincopyprint?<meta-data android:name="android.app.lib_name" android:value="unity" /> <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" /> 这样问题是解决了,可是我们得搞懂为什么吧,在Unity官方文档中,我们找到了答案:

请注意,NativeActivity在Android2.3以后被引入而且不支持该版本以下的设备。因为触摸/运动事件处理在本机代码,Java视图通常不会看到这些事件。然而,在统一转发机制允许将事件传播到DalvikVM。为了使用这个机制,您需要修改manifest文件如下:

[html] view plaincopyprint?<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" package="com.company.product"> <application android:icon="@drawable/app_icon" android:label="@string/app_name"> <activity android:name=".OverrideExampleNative" android:label="@string/app_name"> <meta-data android:name="android.app.lib_name" android:value="unity" /> <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 这段话的意思就是说Android的事件是运行在本机代码中的,Java视图是看不到这些事件的,然而我们可以通过Unity提供的统一转发机制将这些事件发送到Android虚拟机,为了使用这个机制,我们必须修改Android的AndroidManifest.xml文件。博主感觉Android插件这块官方目前做得不是很好,总是给人一种云里雾里的感觉,而且通过各种语言相互调用增加了调试的难度,关于Android更多的内容,大家可以参考官方的文档:点击这里.好了,今天的内容就是这样啦,希望大家喜欢。最后再来看看程序运行的效果吧

UnityRandom介绍 介绍UnityRandom是一个针对Unity3D的伪随机数库,使用C#语言开发。代码和文档都在Github上。UnityRandom采用Mersennetwister伪随机数发生算法,能够快速产生高质

游戏简单控制逻辑 一个轻量级的状态机 出处:

三分钟了解LOD在游戏里面的运用 性能优化

标签: Unity3D游戏开发标准教程

本文链接地址:https://www.jiuchutong.com/biancheng/384566.html 转载请保留说明!

上一篇:【猫猫的Unity Shader之旅】之简述3D图形学(猫的喵喵)

下一篇:UnityRandom介绍(unity random.value)

  • 企业转出多交增值税吗
  • 固定资产的更新改造支出计入什么科目
  • 公允价值模式下,投资性房地产不计提折旧或摊销
  • 小规模纳税人专票税率是多少
  • 怎么知道购货方电话号码
  • 私对公转账可以撤回吗
  • 出口企业免抵税额在增值税申报表填写附表5
  • 应收账款未收到回函的替代程序
  • 预算基数是什么
  • 原材料计划成本和实际成本的区别
  • 计提个人社会保险费
  • 人力资源外包服务规范
  • 取得建安类专用发票能抵扣进项税吗
  • 地质勘察费用应由谁支付
  • 每股收益的无差别点小于息税前利润选择什么筹资方式
  • 退税后钱到哪里
  • 保险营销员的佣金怎么算个税
  • 办理出口退税需要的资料
  • 个人房源可以委托别人吗
  • 增值税发票备注栏不写可以吗
  • 没收入就没附加税么?
  • 产品定价的含义
  • 对公银行转账给私卡做备用金应怎样做分录?
  • 采购发票主要包括什么可以根据什么单据流转生成
  • 在售房地产土地使用税如何计算?
  • window如何打开控制台
  • 税收滞纳金能不能超过本金
  • 上个月退货会计分录
  • win11怎么安装CAD2008
  • 收到政府补贴的装修款
  • windows无法自动检测网络代理设置该怎么办
  • PHP:preg_replace_callback()的用法_PCRE正则函数
  • 如何做批发
  • 预提费用是啥
  • 发票盖章有讲究吗
  • 修建污水处理厂施工方案包括哪些内容
  • php foo
  • 劳务公司账务处理办法
  • 受托代销商品会计分录受托方
  • 汇兑应计入哪个科目
  • mac环境搭建
  • thinkphp in
  • list删除某个元素 python
  • 成品油电子普通发票如何入账
  • 如何设置linux
  • 自由会计师
  • 跨年租金如何确权
  • 小微企业买商品房怎么买
  • 口罩属于什么经济分类
  • 专项附加扣除批量上传怎么上传
  • 消费税是在哪个环节缴纳
  • 七天年化收益率2%
  • 长期待摊费用做账
  • 应付账款长时间收不回怎么处理呢
  • 运输费用如何做账
  • 小规模红冲发票怎么做分录
  • 进销存怎么看
  • 购买的材料入库属于什么会计科目
  • 收履约保证金的会计分录
  • 制造费用结转到哪个科目
  • 股东变更需要哪些资料和手续
  • sql server中事务有哪三种语句
  • mysql 5.7启动
  • linux操作系统的安装步骤
  • win7工具栏怎么调整
  • mtask.exe - mtask是什么进程 有什么用
  • windows8.1的设置在哪
  • Win7怎么开启存储感知
  • win10一直显示正在启动
  • 安卓opengl es
  • jquery获取本地ip
  • nodevideo翻译
  • 常用的linux命令大全
  • javascript面向对象精要pdf
  • jqueryapi手机版
  • 发票在国家税务总局网站查不到能用吗
  • 广西发票查询平台
  • 昆山国税局上班时间
  • 地税局社保宣传标语
  • 地税局网上报税
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设