位置: 编程技术 - 正文

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)

  • 个体工商户要做帐吗
  • 取得的高速公路发票可以抵扣吗
  • 现金流量表现金流量项目明细分类
  • 建筑工程怎么确定施工工程进度
  • 房产报废手续
  • 汇算清缴所得税补缴怎么处理
  • 进项大于销项的会计分录怎么做?
  • 附加税减半征收政策从什么时候开始
  • 已认证未抵扣的进项怎么填写
  • 增值税专用发票电子版
  • 企业改制重组增值税优惠政策
  • 食堂买菜未取得消费凭证
  • 烟叶收购方案制定步骤
  • 合伙企业无偿获得股权怎么缴税?
  • 企业收到个体户开的发票
  • 哪些项目需要征税
  • 定额发票有效期是多长时间?你知道吗?
  • 企业上市过程中遇到的困难
  • 税务局如何检查上传的发票
  • 税务申报没报上怎么办
  • 应收账款坏账处理审计
  • 免税销售额计入主营业务收入吗
  • 存货跌价准备如何结转
  • 审图费发票需要备注吗
  • 股权转让的会计凭证
  • php中substr()
  • linux相关命令及用法
  • 赔偿款支出会计处理
  • PHP:Memcached::getVersion()的用法_Memcached类
  • 未分配利润可以用来干什么
  • 什么情形不属于经警告无效人民警察可以使用武器的情形
  • 知识产权作用
  • 农村土地承包经营权证丢失怎么补办
  • 财务管理公司属于什么行业类别
  • 维多利亚国家艺术馆
  • 餐饮专用发票可抵扣吗
  • 知识产权专利费包括哪些费用
  • php中foreach循环遍历数组
  • es6特性及使用场景
  • 其他应收款的核算范围包括
  • 销售方开具的红字信息表
  • 个人所得税经营所得
  • 劳务费个税扣税
  • phpcms怎么用
  • php验证码代码怎么写
  • sql已成功与服务器建立连接但登录中发生错误
  • sql server 2008使用
  • sqlserver2005安装失败
  • 通货膨胀率怎么求
  • 关于税务机关扣押程序
  • 行政事业单位职工工伤有哪些待遇
  • 汽车维修公司做账基本流程
  • 补计提去年所得税会影响当月资产
  • 失控发票进项税额结转成本
  • 小规模购置金税盘抵税如何申报
  • 忘了作废的发票还能用吗
  • 应收账款应付账款借贷方都表示什么
  • 购买不良债权如何追偿
  • 分包开给总包的票,能不能抵扣
  • 增值税发票红冲和作废的区别
  • 企业应当在
  • 根据企业
  • 内账咋做
  • SQLServer2000 报1053错误(服务没有及时响应或控制请求)的解决方法
  • 如何将windows 7升级到windows 10
  • service.exe是什么
  • win 8.1激活
  • win8如何使用网页版的onedrive
  • qqlogin.exe是什么进程 qqlogin.exe应用程序错误解决办法
  • 观察者模式指令
  • cocos creator开发文档
  • cocos2dx4.0入门
  • jquery 图片预览
  • dos批处理文件的扩展名
  • JavaScript中常用的数据类型有
  • linux进程监控方法
  • jqueryw3c
  • 安卓音频分析软件
  • html5table
  • 税控盘怎么领用
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设