2011-10-12 03:27:47 iteye_20117 阅读数 58
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4644 人正在学习 去看看 张刚
Unity3D虚拟聊天室演示

[url=http://zijan.byethost6.com]http://zijan.byethost6.com[/url]

用Unity3D做的3D聊天室,像flash一样,第一次运行需要先安装Unity3D浏览器插件。

此Demo是为了检验QGF,一个基于Unity3D的游戏架构。
QGF是多个游戏核心模块的集合,包括了:游戏资源加载,脚本控制,摄像头,输入设备(键盘鼠标),事件机制,游戏界面,网络传输...等等

整个Demo,U3D客户端用C#编写,直接socket连接用Java编写的服务器端程序。后端程序使用NIO2,实现了高速异步跨平台跨语言的网络通讯。

MMOCC Demo V0.4 2011.12.15 update:
1)加入了室外场景
2)实现后台场景资源下载
3)加入多个NPC
4)修改的N个Bug

MMOCC Demo V0.3 2011.11.30 update:
1)加入了布置房间的功能
2)支持多语言
3)可以实时更换GUI皮肤
4)加入了GUI Debug窗口功能,Ctrl+Alt+D

MMOCC Demo V0.2
[url]http://qileyuan.cu.cc[/url]
1)加入聊天窗口
2)支持网络联机

[img]http://dl.iteye.com/upload/attachment/0060/5940/6f9d32f2-2f1f-35fe-a74e-0e4af46a18af.jpg[/img]

[img]http://dl.iteye.com/upload/attachment/0063/1664/80ee5d3a-4ada-30b5-bf57-bc5228caed58.jpg[/img]

[img]http://dl.iteye.com/upload/attachment/0063/1666/c79295a8-53f4-317a-80a9-09811b9f82d0.jpg[/img]

什么是MMOCC?
MMOCC是Massive Multiplayer Online Chat Community的缩写,即大型在线聊天虚拟社区。其中有一些比较典型的特征(网上找的我就不翻译了):
1) Avatar Creation (Design character with change of hair, clothes, pants, shoes, and colors)
2) Chatting (Chat is entered, appears in the game inside a chat bubble, and eventually disappears)
3) Credit System to purchase virtual items, clothes, etc)
4) Catalogue System (Add items, Lists all items, a user can purchase an item with credits, and their credits get adjusted. The item is put in their inventory)
5) Items (Create for the users, Can be moved, placed, and rotated inside rooms, or placed into the users inventory)
6) Walking/Talking (Users click to move to a position, can walk around objects, behind objects, interact with objects)
7) Trading (Users can exchange items for other items, or for credits- with another user)
8) Admin System (Can manage other users information, credits, Ban Users, Mute Users, etc)
9) Room Creation (Users can create a virtual room, name it, lock it, unlock it, place items inside it, and decorate it with virtual items)
10) Friend List (Users can add friends to a friends list, and private message them in-game)
11) User Items (Users can create their own objects and sell)
12) Stores Users (Users can create their own shops and businesses which offer services or items in exchange for credits)
MMOCC游戏不再以打怪升级为目的,而是以交友模拟现实生活为主,游戏中万事万物皆可自定义,小到玩家脸上的眉毛,大到建筑的外观,玩家甚者可以自己上传游戏道具和图片,和另外的玩家交换或销售。玩家还可以在游戏中玩游戏,足不出户的和好友举行party,看最新上映的电影,网购自己喜欢的商品。公司可以在游戏中发布广告展示产品,举行线上活动。有人说这就是未来的终极游戏,WEB3.0的一部分。目前属于这一类型的代表游戏有Second Life,PSHome,Webkinz。
2015-07-15 11:11:36 pizi0475 阅读数 4388
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4644 人正在学习 去看看 张刚

众所周知,Unity3D是一个能够实现轻松创作的多平台的游戏开发工具,是一个全面整合的专业游戏引擎。在现有的版本中,其强大的游戏制作功能已经达到和其他顶级游戏引擎媲美的地步。但是 其制作并不如想象中的困难。本文就带您走进unity的世界,并且看看第一个游戏demo是什么样的。

AD:

众所周知,Unity3D是一个能够实现轻松创作的多平台的游戏开发工具,是一个全面整合的专业游戏引擎。在现有的版本中,其强大的游戏制作功能已 经达到让人瞠目结舌的地步。尤其是它在3.0版本里面制作的那款第一人称战争游戏,画质效果丝毫不逊色于当下十分流行的《穿越火线》、《战地之王》等主流 第一人称射击游戏。下图为Demo中的显示效果:

1.JPG

看到如此绚丽的效果,让我马上走进精彩的Unity3D世界吧!首先要下载Unity3D,在官网上就可以完成。
Unity3D的官方网站:http://unity3d.com
Unity3D的下载地址:http://unity3d.com/unity/download/
下载好之后,必须要到官方网站上注册一个邮箱,才能获得30天的试用时间。试用后如果您对这款软件满意,还可以在购买后继续使用。当然,如果您购买了Pro版本的Unity3D,将会获得更多的功能。
第一章Unity3D的基本界面介绍

Unity3D的基本界面非常简单,几个窗口就可以实现几乎全部的编辑功能。主界面如图1.1所示:
2.JPG

场景面板
:该面板为Unity3D的编辑面板;您可以将您所有的模型、灯光、以及其他材质对象拖放到当前场景中。构建游戏中所能呈现的景象。
动画面板:与场景面板不同,该面板是用来渲染场景面板中的景象的。该面板不能用作编辑,但却可以呈现完整的动画效果。显示的内容取决于场景摄像机的设置。
层次清单栏:该面板主要功能是显示放在场景面板中的所有的物体对象。
项目文件栏:该面板主要功能是显示该项目文件中的所有资源列表。除了模型、材质、字体等,还包括该项目的各个场景文件。
对象属性栏:该面板栏会呈现出任何对象的固有属性,包括三维坐标、旋转量、缩放大小、脚本的变量和对象等等。
场景调整工具:可以改变您在编辑过程中的场景视角、物体世界坐标和本地坐标的更换、物体的法线中心的位置,以及物体在场景中的坐标位置,缩放大小等等。

菜单栏:接下来我重点介绍一下菜单栏。

菜单栏中包含有八个菜单选项:分别是File【文件】、Edit【编辑】、Assets【资源】、GameObject【游戏对象】、Component【组件】、Terrain【地形】、Window【窗口】、Help【帮助】。

每个菜单选项又有自己的子菜单,总结如下:

1、File【文件】

3.JPG

名称
说明
New Scene 创建新的场景。就像是游戏中的一个一个的场景一样,Unity3D为用户提供了方便的场景管理,用户可以随心所欲的创建出自己想要的场景。然后再把每个场景链接起来组成一个完成的游戏。

Open Scene 打开一个已经创建的场景
Save Scene 保存当前场景
Save Scene as 当前场景另存为
New Project 新建一个新的项目工程。用户想要制作出自己的游戏,第一步就是创建一个属于这个游戏的工程,这个工程是所有元素的基础。有了工程之后,用户就可以在这个工程里面添加自己的场景。
Open Project 打开一个已经创建的工程
Save Project 保存当前项目
Build Setting 项目的编译设置。在编译设置选项里面,用户可以选择游戏所在的平台及对工程中的各个场景之间的管理。可以添加当前的场景加入到工程的编译队列当中。其中的Player Settings选项中可以设置程序的图标,分辨率,启动画面等。
Build & Run 编译并运行项目
Exit 退出Unity3D

2、Edit【编辑】

4.JPG

名称
说明
Undo 撤销上一步操作
Redo 重复上一步动作
Cut 剪切
Copy 复制
Paste 粘贴
Duplicate 复制并粘贴
Delete 删除
Frame Selected 选择一个物体后,使用此功能可以把视角调到观察这个选中的物体上
Find 在资源区可以按资源的名称来查找
Select All 可以选中所有资源
Preferences 选项设置。对Unity3D的一些基本设置,如:选用外部的脚本编辑,皮肤,各种颜色的设置。以及一些用户基本的快捷键的设置。
Play 编译并在Unity3D中运行程序
Pause 停止程序
Step 单步执行程序
Load Selection 载入所选
Save Selection 保存所选
Project Settings

项目设置。其中包括输入设置,标签设置(对场景中的元素设置不同类型的标签,方便场景的管理),音频设置,运行的时间的设置,用户设置,物理设置(包括重 力,弹力,摩擦力等),品质设置(这个比较重要,用户在这个选项里面可以设置工程默认的渲染品质),网络管理,编辑器管理等

Render Settings 渲染设置。如果觉得整体画面的色彩质量不尽如人意,可在此处进行调节
Graphics Emulation 图形仿真。主要是配合一些图形加速器的处理
Network Emulation 网络仿真。可以选择相应的网络类型进行仿真
Project Settings 项目设置。其中包括输入设置,标签设置,音频设置,运行的时间的设置,用户设置,物理设置,品质设置,网络管理,编辑器管理等。
Snap Settings 临时环境,或理解为快照设置。

3、Assets【资源】

5.JPG

名称
说明
Reimport 重新导入资源
Create 创建功能。可以用来创建各种脚本,动画,材质,字体,贴图,物理材质,GUI皮肤等
Show In Explorer 打开资源所在的目录位置
Open 打开选中文件
Delete 删除选中的资源文件
Import New Asset 导入新的资源
Refresh 刷新,用于导入资源包之后
Import Package 导入资源包。当创建项目工程的时候,有些资源包没有导入进来,在开发过程中有需要使用,这时可以用到导入资源包的功能
Export Package 到处资源包
Select Dependencies 选择依赖项
Reimport 全部重新导入
Sync MonoDevelop Project 同步开发项目

4、GameObject【游戏对象】

6.JPG

名称
说明
Create Empty 创建一个空的游戏对象。可以对这个空的对象添加各种组件,即各种属性。在Component里面会讲到
Create Other 创建其他类型的游戏对象。这里面包括了很多内容,基本上囊括了Unity3D所支持的所有对象。其中有粒子系统,摄像机,界面文字,界面贴图,3D的文字效果,点光源,聚光灯,平行光,长方体,球,包囊,圆柱体,平面,表面,音频混音区域,树,玩偶,风域等
Center On Children 这个功能是作用在父节点上的,即把父节点的位置移动到子节点的中心位置
Make Parent 选中多个物体后,点击这个功能可以把选中的物体组成父子关系,其中在层级视图中最上面的那个为父节点,其他为这个节点的子节点
Apply Change To Prefab 应用变更为预置
Move To View 这个功能经常用到,把选中的物体移动到当前编辑视角的中心位置,这样就可以快速定位
Align With View 把选中的物体移动到当前编辑视角的中心位置,深度为0,即移动到和视角同一个平面上
Align View To Selected 把编辑视角移动到选中物体的中心位置

5、Component【组件】

7.JPG

名称

说明
Mesh 添加网格属性
Particles 粒子系统。能够造出很棒的流体效果
Physics 物理系统。可以使物体带有对应的物理属性
Audio 音频。可以创建声音源和声音的听者
Rendering 渲染
Miscellaneous 杂项
Scripts 脚本。Unity内置的一些功能很强大的脚本
Camera-Control 摄像机控制

6、Terrain【地形】

8.JPG

名称
说明

Creat Terrain 创建地形
Import Heightmap-Raw 导入高度图
Export Heightmap-Raw 到处高度图
Set Resolution 设置分辨率
Create Lightmap 创建光影图
Mass Place Trees 批量种植树
Flatten Heightmap 展平高度图
Refresh Tree And Detail Prototypes 刷新树及预置细节

7、Window【窗口】

9.JPG

名称
说明
Next Window 下个窗口
Previous Window 前一个窗口
Layouts 布局
Scene 场景窗口
Game 游戏窗口
Inspector 检视窗口,主要指各个对象的属性,也可称为属性面板
Hierarchy 层次窗口
Project 工程窗口
Animation 动画窗口。用于创建时间动画的面板

Profiler 探查窗口
Asset Server 源服务器
Console 控制台

第二章 Unity3D的简单预览

每个Unity3D版本都会自带一个Demo源文件。在3.0的正式版中,自带的Demo就是网上展示的那款强大的射击游戏。在一般情况下,您只要第一次 打开Unity3D v3.0就会看见自带的那个Demo项目文 件了。但如果Unity3D并没有打开这个项目文件,你也可以在Unity3D里面的“File”菜单下点击“Open Project”选项,在“C:\Documents and Settings\All Users\Documents\Unity Projects”这个路径下找到项目文件夹“Bootcamp Demo”,选择并打开它。打开项目之后,在舞台场景面板中依然什么都没有显示的话,请在Project【项目文件栏】双击场景文件 1.JPG 。稍等片刻之后,该舞台场景的所有对象就可以导入到舞台场景之中。导入成功之后效果如图2.1所示:
2.JPG

点击一下中间的播放按钮 3.JPG 做一下测试(如果您的机器配置不是很高,可能等待的时间会稍长)。稍等片刻,您就可以在Game【动画面板】中看到一个正在运行的射击游戏了。
在这个游戏场景中,您会看到比其他主流游戏还要细腻逼真的画面效果,例如各个物体的实时阴影。如图2.2所示:
4.JPG
当然如果您的机器配置较高,您还可以点击“Esc”键来将游戏画质进一步调高。调节界面如图2.3所示:
5.JPG
下面我们来看下调整画面效果前后的游戏画面对比,如图2.4.1和图2.4.2所示:
6.JPG
7.JPG
我们很明显的就可以感觉到河水的效果以及场景阴影的效果都真实了许多。

【责任编辑:Pockey TEL:(010)68476606】


2014-08-22 15:03:29 hackdjh 阅读数 4353
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4644 人正在学习 去看看 张刚

效果展示:


unity3d,嵌入,3d,android,展示0 unity3d,嵌入,3d,android,展示1unity3d,嵌入,3d,android,展示2

unity3d,嵌入,3d,android,展示3    unity3d,嵌入,3d,android,展示4     unity3d,嵌入,3d,android,展示5    unity3d,嵌入,3d,android,展示6


开篇废话:

我现在所在的Team每周需要一个人给大家介绍一个知识点,或者新技术。这礼拜正好轮到我了,由于我工作才一年,面对那帮老鸟讲知识点感觉有点作死。所以我就准备选个新技术介绍一下。

由于我在大学里自学过一段时间Unity3D,所以我想介绍的技术就是它,但我现在做的是应用开发,不能做个小游戏去给大家演示。所以我想到比较简单,直观,而且有可能真正能用到的就是在Android应用中展示3D模型。比如在产品展示时直接把这个产品的3D模型展示出来而不是个图片,效果应该非常棒(OpenGL应该也可以做)。

思路定下以后就发现大学时学的Unity3D的内容基本忘光了,虽然偶尔有Unity3D的文章都会点开看看,但还是得重新学。记得当时学Unity3D的时候看过一个叫雨松MOMO的博客。那时年轻,懵懂,找不到方向的我还给雨松大神发了一封邮件去请教大学应该怎么学习和做游戏相关的问题,结果人家没回,导致我更加失落于是接着学android去了。。。又扯远了。。。于是我又找到他的博客,把Unity3D基础部分的相关文章都看了一遍。

但是他博客里有介绍如何在Unity3D中调用Android,而我想做的是在Android中调用Unity3D,而且是把Unity3D嵌套在ANDROID的视图里面。最后费了九牛二虎之力才把这个Demo做出来。


准备工作:

下面是我总结的流程,目的是使本文思路更加清晰一些:

1.Android端代码可以在Eclipse中开发(AndroidStudio没有试,应该也可以)

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中的代码都贴出来,如果我注解有不对的地方希望大家指正。

  1. /** 
  2.  * UnityPlayerActivity,UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity 
  3.  * 而UnityPlayerNativeActivity继承自NativeActivity 
  4.  * 在该类里定义了一些和ANDROID生命周期相同的回调方法,留给自定义的Activity子类重写。 
  5.  */  
  6. public class UnityPlayerNativeActivity extends NativeActivity  
  7. {  
  8.     //UnityPlayer的引用,并且我们不能改变这个引用变量的名字,它被native code所引用  
  9.     protected UnityPlayer mUnityPlayer;  
  10.   
  11.     protected void onCreate (Bundle savedInstanceState)  
  12.     {  
  13.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  14.         super.onCreate(savedInstanceState);  
  15.         // 设置显示窗口参数  
  16.         getWindow().takeSurface(null);  
  17.         setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);  
  18.         getWindow().setFormat(PixelFormat.RGB_565);  
  19.   
  20.         // 创建一个UnityPlayer对象,并赋值给全局的引用变量  
  21.         mUnityPlayer = new UnityPlayer(this);  
  22.         //为UnityPlayer设置一些参数  
  23.         if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar"true))  
  24.             getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  25.                                    WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  26.   
  27.         int glesMode = mUnityPlayer.getSettings().getInt("gles_mode"1);  
  28.         boolean trueColor8888 = false;  
  29.         // UnityPlayer.init()方法需要在将view附加到layout之前调用。它将会调用native code  
  30.         mUnityPlayer.init(glesMode, trueColor8888);  
  31.           
  32.         // 从UnityPlayer中获取到Unity的View视图  
  33.         View playerView = mUnityPlayer.getView();  
  34.         // 将Unity视图加载到根视图上  
  35.         setContentView(playerView);  
  36.         // 使Unity视图获取焦点  
  37.         playerView.requestFocus();  
  38.     }  
  39.     protected void onDestroy ()  
  40.     {  
  41.         // 当Activity结束的时候调用UnityPlayer.quit()方法,它会卸载之前调用的native code  
  42.         mUnityPlayer.quit();  
  43.         super.onDestroy();  
  44.     }  
  45.   
  46.     // 下面几个方法都是ANDROID相关回调方法,确保在ANDROID执行相应方法时UnityPlayer也需调用相应方法  
  47.     protected void onPause()  
  48.     {  
  49.         super.onPause();  
  50.         mUnityPlayer.pause();  
  51.     }  
  52.     protected void onResume()  
  53.     {  
  54.         super.onResume();  
  55.         mUnityPlayer.resume();  
  56.     }  
  57.        
  58.     public void onConfigurationChanged(Configuration newConfig)  
  59.     {  
  60.         super.onConfigurationChanged(newConfig);  
  61.         mUnityPlayer.configurationChanged(newConfig);  
  62.     }  
  63.     public void onWindowFocusChanged(boolean hasFocus)  
  64.     {  
  65.         super.onWindowFocusChanged(hasFocus);  
  66.         mUnityPlayer.windowFocusChanged(hasFocus);  
  67.     }  
  68.     public boolean dispatchKeyEvent(KeyEvent event)  
  69.     {  
  70.         if (event.getAction() == KeyEvent.ACTION_MULTIPLE)  
  71.             return mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event);  
  72.         return super.dispatchKeyEvent(event);  
  73.     }  
  74. }  
看完这个类后就知道了为什么在自定义的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,因为名字最简单,觉得该封装的都应该封装好了。

  1. public class MainActivity extends UnityPlayerActivity {  
  2.       
  3.     private Button topButton;  
  4.     private Button bottomButton;  
  5.       
  6.     @Override  
  7.     protected void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.           
  10.         // 设置test为我们的根布局  
  11.         setContentView(R.layout.test);  
  12.           
  13.         // 通过刚才的源码分析,知道mUnityPlayer为一个全局的引用变量,而且已经在父类中设置好了,所以直接拿来用就可以了  
  14.         View playerView = mUnityPlayer.getView();  
  15.         // 将Unity的视图添加到我们为其准备的父容器中  
  16.         LinearLayout ll = (LinearLayout) findViewById(R.id.unityViewLyaout);  
  17.         ll.addView(playerView);  
  18.           
  19.         // 上面的button设置监听器  
  20.         topButton = (Button) findViewById(R.id.topButton);  
  21.         topButton.setOnClickListener(new View.OnClickListener() {  
  22.   
  23.             @Override  
  24.             public void onClick(View v) {  
  25.                 //发送消息给Unity端,该函数第一个参数为接受消息的类对象,第二个该类对象用接受消息的方法,第三个参数为传递的消息  
  26.                 //所以下面的意思就为:调用Main Camera下面的Previous方法,传送的消息为空  
  27.                 UnityPlayer.UnitySendMessage("Main Camera","Previous","");   
  28.             }  
  29.         });  
  30.           
  31.         // 为下面的button设置监听器  
  32.         bottomButton = (Button) findViewById(R.id.bottomBtn);  
  33.         bottomButton.setOnClickListener(new View.OnClickListener() {  
  34.               
  35.             @Override  
  36.             public void onClick(View v) {  
  37.                 //调用Main Camera下面的Next方法,传送的消息为空  
  38.                 UnityPlayer.UnitySendMessage("Main Camera","Next","");     
  39.             }  
  40.         });  
  41.     }  
  42. }  

最后看一下Android端的布局文件,布局很简单,上下各有一个button按钮,两个按钮中间是Unity的视图。

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <Button  
  8.         android:id="@+id/topButton"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_alignParentTop="true"  
  12.         android:text="PREVIOUS" />  
  13.   
  14.     <LinearLayout  
  15.         android:id="@+id/unityViewLyaout"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="match_parent"  
  18.         android:layout_above="@+id/bottomBtn"  
  19.         android:layout_below="@+id/topButton"  
  20.         android:orientation="horizontal" >  
  21.     </LinearLayout>  
  22.   
  23.     <Button  
  24.         android:id="@+id/bottomBtn"  
  25.         android:layout_width="match_parent"  
  26.         android:layout_height="wrap_content"  
  27.         android:layout_alignParentBottom="true"  
  28.         android:text="NEXT" />  
  29.   
  30. </RelativeLayout>  
Android端的代码就介绍完了,很简单。唯一的难点就是UnityPlayerActivity和UnityPlayer的使用,就这两个破玩意花了我好几天的时间,很简单的东西不知道为什么官方不给个文档或者API(也可能我太挫没找到。。。) 

Unity3D端代码:

先看一下我的项目结构:

unity3d,嵌入,3d,android,展示7

JavaScript存放的是脚本

Models存放的是我在Assert Store中下载的免费的一些模型文件

Plugins下是我的Android工程,具体做法参考网上教程(这里推荐雨松大神的第17篇)

Prefab我是调整模型后定义的预制体

在场景中,我只有一个摄像机,和一个直射光。将脚本绑定到摄像机上,然后将之前调整好的5个预设模型添加到脚本的相应对象中。

unity3d,嵌入,3d,android,展示8

下面是脚本的代码,关于模型的旋转缩放是直接用了雨松MOMO的一篇文章中的代码,然后再加上了本例中的一些逻辑而组成的。

  1. #pragma strict  
  2.   
  3. //5个模型,从外部传入  
  4. var car : GameObject;  
  5. var helicopter : GameObject;  
  6. var suv : GameObject;  
  7. var plane : GameObject;  
  8. var tank : GameObject;  
  9.   
  10. //模型数组下标  
  11. private var index : int;  
  12. //模型数组  
  13. private var models : GameObject[];  
  14. //当前模型对象  
  15. private var mCurrentGameObject : GameObject;  
  16.   
  17. /******************************************/  
  18. /*分割线之下的变量用于触摸手势镜头控制旋转和缩放*/  
  19. /******************************************/  
  20.   
  21. //缩放系数  
  22. var distance = 10.0;  
  23. //左右滑动移动速度  
  24. var xSpeed = 250.0;  
  25. var ySpeed = 120.0;  
  26. //缩放限制系数  
  27. var yMinLimit = -20;  
  28. var yMaxLimit = 80;  
  29. //摄像头的位置  
  30. var x = 0.0;  
  31. var y = 0.0;  
  32. //记录上一次手机触摸位置判断用户是在左放大还是缩小手势  
  33. private var oldPosition1 : Vector2;  
  34. private var oldPosition2 : Vector2;  
  35.   
  36.   
  37. function Start () {  
  38.     //初始化模型数组  
  39.     index = 0;  
  40.     models = new GameObject[5];  
  41.     models[0] = car;  
  42.     models[1] = helicopter;  
  43.     models[2] = suv;  
  44.     models[3] = plane;  
  45.     models[4] = tank;  
  46.     //克隆一个初始模型对象  
  47.     mCurrentGameObject = Instantiate(models[index], Vector3(0,0,0), Quaternion.Euler(-20,0,0));   
  48.       
  49.     //初始化镜头参数  
  50.     var angles = transform.eulerAngles;  
  51.     x = angles.y;  
  52.     y = angles.x;  
  53. }  
  54.   
  55. function Update () {  
  56.   
  57.     //判断触摸数量为单点触摸  
  58.     if(Input.touchCount == 1)  
  59.     {  
  60.         //触摸类型为移动触摸  
  61.         if(Input.GetTouch(0).phase==TouchPhase.Moved)  
  62.         {  
  63.             //根据触摸点计算X与Y位置  
  64.             x += Input.GetAxis("Mouse X") * xSpeed * 0.02;  
  65.             y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;  
  66.    
  67.         }  
  68.     }  
  69.    
  70.     //判断触摸数量为多点触摸  
  71.     if(Input.touchCount > 1 )  
  72.     {  
  73.         //前两只手指触摸类型都为移动触摸  
  74.         if(Input.GetTouch(0).phase==TouchPhase.Moved||Input.GetTouch(1).phase==TouchPhase.Moved)  
  75.         {  
  76.                 //计算出当前两点触摸点的位置  
  77.                     var tempPosition1 = Input.GetTouch(0).position;  
  78.                 var tempPosition2 = Input.GetTouch(1).position;  
  79.                 //函数返回真为放大,返回假为缩小  
  80.                 if(isEnlarge(oldPosition1,oldPosition2,tempPosition1,tempPosition2))  
  81.                 {  
  82.                     //放大系数超过3以后不允许继续放大  
  83.                     //这里的数据是根据我项目中的模型而调节的,大家可以自己任意修改  
  84.                        if(distance > 3)  
  85.                        {  
  86.                            distance -= 0.5;  
  87.                        }  
  88.                    }else  
  89.                 {  
  90.                     //缩小洗漱返回18.5后不允许继续缩小  
  91.                     //这里的数据是根据我项目中的模型而调节的,大家可以自己任意修改  
  92.                     if(distance < 18.5)  
  93.                     {  
  94.                         distance += 0.5;  
  95.                     }  
  96.                 }  
  97.             //备份上一次触摸点的位置,用于对比  
  98.             oldPosition1=tempPosition1;  
  99.             oldPosition2=tempPosition2;  
  100.         }  
  101.     }  
  102. }  
  103.   
  104. //函数返回真为放大,返回假为缩小  
  105. function isEnlarge(oP1 : Vector2,oP2 : Vector2,nP1 : Vector2,nP2 : Vector2) : boolean  
  106. {  
  107.     //函数传入上一次触摸两点的位置与本次触摸两点的位置计算出用户的手势  
  108.     var leng1 =Mathf.Sqrt((oP1.x-oP2.x)*(oP1.x-oP2.x)+(oP1.y-oP2.y)*(oP1.y-oP2.y));  
  109.     var leng2 =Mathf.Sqrt((nP1.x-nP2.x)*(nP1.x-nP2.x)+(nP1.y-nP2.y)*(nP1.y-nP2.y));  
  110.     if(leng1 < leng2)  
  111.     {  
  112.          //放大手势  
  113.          return true;  
  114.     }else  
  115.     {  
  116.         //缩小手势  
  117.         return false;  
  118.     }  
  119. }  
  120.    
  121. //Update方法一旦调用结束以后进入这里算出重置摄像机的位置  
  122. function LateUpdate () {  
  123.    
  124.     //mCurrentGameObject为我们当前模型对象,缩放旋转的参照物  
  125.     if (mCurrentGameObject.transform) {          
  126.    
  127.         //重置摄像机的位置  
  128.          y = ClampAngle(y, yMinLimit, yMaxLimit);  
  129.         var rotation = Quaternion.Euler(y, x, 0);  
  130.         var position = rotation * Vector3(0.00.0, -distance) + mCurrentGameObject.transform.position;  
  131.    
  132.         transform.rotation = rotation;  
  133.         transform.position = position;  
  134.     }  
  135. }  
  136.    
  137. static function ClampAngle (angle : float, min : float, max : float) {  
  138.     if (angle < -360)  
  139.         angle += 360;  
  140.     if (angle > 360)  
  141.         angle -= 360;  
  142.     return Mathf.Clamp (angle, min, max);  
  143. }  
  144.   
  145. // 当android中按下next,显示下一个模型  
  146. function Next () {  
  147.     index = index+1;  
  148.     if (index > models.Length-1) {  
  149.         index = 0;  
  150.     }  
  151.     Debug.Log("next");  
  152.     // 摧毁当前对象  
  153.     Destroy(mCurrentGameObject);  
  154.     // 建立新的模型对象  
  155.     mCurrentGameObject = Instantiate(models[index]);  
  156. }  
  157.   
  158. // 当android中按下previous,显示上一个模型  
  159. function Previous () {  
  160.     index = index-1;  
  161.     if (index < 0) {  
  162.         index = models.Length-1;  
  163.     }  
  164.     Debug.Log("previous");  
  165.     // 摧毁当前对象  
  166.     Destroy(mCurrentGameObject);  
  167.     // 建立新的模型对象  
  168.     mCurrentGameObject = Instantiate(models[index]);  
  169. }  

最后就是在Unity3D中将工程Build成APK文件,然后再手机或模拟器中运行(如果手机或模拟器连着Eclipse则可以打出log方便调试找错)。

最后附上代码Demo:

Unity端代码太大了,所以我就把Android端和Unity端代码上传到百度云了。而apk文件上传到csdn,如果只想看效果的可以下载来试试。

代码点击下载

2019-05-30 16:21:42 cre2017 阅读数 581
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4644 人正在学习 去看看 张刚

下载xlua

https://github.com/Tencent/xLua

安装xlua到unity工程

1 解压后的目录如下在这里插入图片描述
2 将Assets目录下的文件复制到Unity工程的Assets目录下
3 将Tools整个目录复制到Unity工程与Assets的同目录下
4 配置宏
在File/Build Settings/Player Settings,设置Scripting_Define_Symbols的值为HOTFIX_ENABLE
如上步骤后,会发现菜单上多了一个XLua菜单
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

运行测试

1 打开XLua/Examples/08_Hotfix的 Hotfix_Test
2 在菜单XLua下,先点击Generate Code等待编译完成后,再点击Hotfix Inject In Editor,再次等待编译
3 运行,观察到控制台输出为update in c#
4 点击Hotfix,观察到控制台输出

LUA: <<<<<<<<Update in lua, tick = 9350 UnityEngine.Debug:Log(Object)
XLua.StaticLuaCallbacks:Print(IntPtr) (at
Assets/XLua/Src/StaticLuaCallbacks.cs:629)
XLua.LuaDLL.Lua:lua_pcall(IntPtr, Int32, Int32, Int32)
XLua.DelegateBridge:PCall(IntPtr, Int32, Int32, Int32) (at
Assets/XLua/Src/DelegateBridge.cs:138)
XLua.DelegateBridge:__Gen_Delegate_Imp14(Object) (at
Assets/XLua/Gen/DelegatesGensBridge.cs:340)
XLuaTest.HotfixTest:Update()
这样我们就实现了lua调用c#
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

新建一个修复脚本HotFixTest1

这里用来加载lua代码到luaEnv中执行,目录是相对路径,放在与Assets同目录下
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;
public class HotFixTest1 : MonoBehaviour {
    private LuaEnv luaEnv;
    private void Awake()
    {
        luaEnv = new LuaEnv();
        luaEnv.AddLoader(HandleCustomLoader);
        luaEnv.DoString("require'fix'");
    }
    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {

    }

    private byte[] HandleCustomLoader(ref string filepath)
    {
        string absPath = filepath + ".lua.txt";
        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(absPath));
    }
    private void OnDisable()
    {
        luaEnv.DoString("require'fixDispose'");
    }
    private void OnDestroy()
    {
        luaEnv.Dispose();
    }


}

新建lua文件测试

1 fix.lua.txt与项目Assets同目录下

--test
UnityEngine = CS.UnityEngine
UnityEngine.Debug.Log("test")

2 fixDispose.lua.txt暂时为空 与项目Assets同目录下

3 将上一步的HotFixTest1脚本挂到场景任意物体上,比如相机上

4 在菜单XLua下,先点击Generate Code等待编译完成后,再点击Hotfix Inject In Editor,再次等待编译
5 观察到输出了test
在这里插入图片描述

为demo搭建一个加载游戏场景

1 场景很简单,一个Slider
在这里插入图片描述
2 新建脚本LoadGame

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class LoadGame : MonoBehaviour {
    public Slider slider;
    
    public string luaPath = @"http://212.64.12.155/unity/demo2/fix.lua.txt";
    // Use this for initialization
    void Start () {
        LoadGameMethod();
    }

    private void LoadGameMethod()
    {
        StartCoroutine(StartLoading(1));
        StartCoroutine(LoadResFromServerCorotine());
    }
    private IEnumerator StartLoading(int scene)
    {
        int displayProgress = 0;
        int toProgress = 0;
        AsyncOperation op = SceneManager.LoadSceneAsync(scene);
        op.allowSceneActivation = false;
        while (op.progress < 0.9f)
        {
            toProgress = (int)op.progress * 100;
            while (displayProgress < toProgress)
            {
                ++displayProgress;
                SetLoadingPercentage(displayProgress);
                yield return new WaitForEndOfFrame();
            }
        }

        toProgress = 100;
        while (displayProgress < toProgress)
        {
            ++displayProgress;
            SetLoadingPercentage(displayProgress);
            yield return new WaitForEndOfFrame();
        }
        op.allowSceneActivation = true;
    }
    private void SetLoadingPercentage(float v)
    {
        slider.value = v / 100;
    }
    IEnumerator LoadResFromServerCorotine()
    {
        UnityWebRequest request = UnityWebRequest.Get(luaPath);
        yield return request.SendWebRequest();
        string str = request.downloadHandler.text;
        string localFilePath = @"./fix.lua.txt";
        File.WriteAllText(localFilePath, str);
    }
    // Update is called once per frame
    void Update () {
		
	}
}

3将LoadGame脚本挂到MainCamera 上,然后吧Slider赋值上
在这里插入图片描述

为demo搭建主场景测试

1 创建text显示当前版本
2 新建GameManager物体
3 新建Manager脚本,内容如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XLua;
using UnityEngine.Networking;
[Hotfix]
public class Manager : MonoBehaviour {
    public Text uitext;
    public GameObject parent;
    public static Dictionary<string, GameObject> prefabDict = new Dictionary<string, GameObject>();

    // Use this for initialization
    public string title = "1.0版本";
    [LuaCallCSharp]
    void Start () {
	}
	
	// Update is called once per frame
	void Update () {
        setText(title);
	}
   public void setText(string text)
    {
        uitext.text = text;
    }
    public void LoadResource(string resName, string filePath)
    {
        StartCoroutine(LoadResourceCorotine(resName, filePath));
    }
    //产生游戏物体
    private void CreateGameObject(GameObject go)
    {
        GameObject goPrefab = Instantiate(go, Vector3.zero, Quaternion.identity);
        goPrefab.transform.parent = parent.transform;
        goPrefab.transform.localPosition = Vector3.zero;
    }
    IEnumerator LoadResourceCorotine(string resName, string filePath)
    {
        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(@"http://212.64.12.155/unity/demo2/AssetBundles/" + filePath);
        yield return request.SendWebRequest();
        AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;

        GameObject go = ab.LoadAsset<GameObject>(resName);
        prefabDict.Add(resName, go);
        CreateGameObject(go);
        Debug.Log("resName=" + resName + ";goName=" + go.name);
    }

}

在这里插入图片描述
4 将Manager脚本挂到GameManager物体上
在这里插入图片描述
5 新建一个text作为prefab,拖到prefabs文件夹,并在右下角设置AssetBundle属性
在这里插入图片描述
好了之后删除场景中的ABTest

完善我们的lua文件

1 fix.lua.txt

--test
UnityEngine = CS.UnityEngine
UnityEngine.Debug.Log("test")
--version to 1.1
xlua.private_accessible(CS.Manager)
xlua.hotfix(CS.Manager,'Start',function(self)
self.title='Version 1.3'
self:LoadResource('ABTest','ab\\test.ab')
end)

2 fixDispose.lua.txt

--dispose
xlua.hotfix(CS.Manager,'Start',nil)

写好之后,将这两个文件上传到服务器,
比如我的服务器位置为:http://xxxxx:80/unity/demo2

新建一个AssetBundle打包工具

1 在Assets目录下新建Editor目录,新建CreateAssetBundle脚本
在这里插入图片描述
2 代码如下:(注意,博主的环境为mac,如果你是windows用户,请更改BuildTarget为StandaloneWindows)


using UnityEditor;
using System.IO;
public class CreateAssetBundle {
    [MenuItem("Assets/Build AssetBundles")]
    static void BuildAllAssetBundles()
    {
        string dir = "./AssetBundles";
        if(Directory.Exists(dir) == false)
        {
            Directory.CreateDirectory(dir);
        }
        BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None,
            BuildTarget.StandaloneOSX);
    }

}

3 回到unity编译,在Assets目录下会出现Build AssetBundles菜单
在这里插入图片描述
点击构建,在工程Assets目录下会出现我们要的ab包
在这里插入图片描述
4 将ab包上传到服务器根目录

运行及一些bug总结

在这里插入图片描述
bugs:
1 如果遇到bug请检查自己的环境版本
2 请注意路径是否正确
3 如果报错,请重新在XLua菜单,重新生成和注入
4 AssetsBundle的构建应该在Xlua环境构建之后,否则会出错

更多参考

【Unity】场景异步加载的进度条制作

https://blog.csdn.net/sinat_20559947/article/details/50000455

Xlua官网

https://github.com/Tencent/xLua

使用指南

https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/hotfix.md

官方FAQ

https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/faq.md

菜鸟教程-Lua教程

http://www.runoob.com/lua/lua-tutorial.html

如何评价腾讯在Unity下的xLua(开源)热更方案?

https://www.zhihu.com/question/54344452/answer/139413144?group_id=800755990562734080

IL(中间语言)

http://blog.csdn.net/dodream/article/details/4726421

玩转xLua的热补丁

http://gad.qq.com/article/detail/42303

xlua的配置

https://github.com/Tencent/xLua/blob/master/Assets/XLua/Examples/ExampleGenConfig.cs

更多

1

学习热更新需要大家到达的程度:

1.什么是Lua,lua的基本用法与语法。
2.什么是ab包,ab包的打包,加载,下载。
3.xlua的一些基础内容,如何开启一个Lua虚拟机工作坏境,如何加载lua文件,怎样在c#里去调lua,在Lua中去调c#。

2 如果有任何问题,可以下方评论,或者加QQ1577432674与本人交流
3 宣传一下交流群:在这里插入图片描述
4 宣传一下个人公众号:edsgame,更多游戏开发干货
在这里插入图片描述
5 完整项目工程链接(也可以加群,群文件有)
链接:https://pan.bai删了我du.com/s/1zUc5L0iUQw5aojXy6a5Ylw 密码:g8yo

2015-12-18 17:18:49 AnYuanLzh 阅读数 2195
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4644 人正在学习 去看看 张刚

Pure MVC是在基于模型、视图和控制器MVC模式建立的一个轻量级的应用框架,这种开源框架是免费的。是一个可应用于多种语言、多种平台的mvc框架。
在这不是一编PureMVC的教程, 而是一个对照 PureMVC C# 版官方demo,改写的Unity3d版,界面是用ugui做的。因为只是用来练手的所以对官方demo有所简化,相信从下面的运行界面截图就看出来:
官方c# demo 截图:
这里写图片描述
我改写的unity3d版 截图:
这里写图片描述

Demo下载

没有更多推荐了,返回首页