2016-09-25 20:06:15 RayFalcon 阅读数 1176
  • Unity3D入门到精通-(4)Unity热更新

    本次系列课程的目标是让Unity3D初学者掌握C语言,Untiy调用lua脚本深入理解uLua框架实现原理,并根据项目的特点实现相应的热更新方案。 适合对象:Unity初学开发者,Unity中级开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    2211 人正在学习 去看看 张刚

体系结构

   为了更好地理解游戏的软件架构和对象模型,它获得更好的外观仅有一名Unity3D的游戏引擎和编辑器是非常有用的,它的主要原则。

Unity3D 引擎

   Unity3D的是一个屡获殊荣的工具,用于创建交互式3D应用程序在多个platforms.Unity3D由游戏引擎和编辑器。该引擎包含的软件组件,在游戏的研究与开发中最常见的和经常性的任务。发动机所涵盖的主题包括声音,图形,物理和网络功能。该引擎支持C#,Boo,和JavaScript脚本编程。
另一个部分是Unity编辑,作为脚本和其他组件,包含游戏场景设置和游戏的预览窗口(见图4)分层对象检查项目面板的集成开发环境。它还配备了几个多语言脚本编辑器和一个独特的预制装配系统,将在后面解释。

  

                                                          图4:Unity3D编辑器

有几个Unity的许可证。Unity基本功能有限的免费PC的MAC和Web  development.Other 的平台或完整的功能集[15]需要购买额外的许可证。
虽然有很多免费软件和专有的替代游戏引擎,如虚幻引擎™或C4™引擎选择了Unity的原因如下:
*它可以部署在Windows,Mac  OSX ,Web浏览器,Wii游戏机,iPhone,iPad的,Android的,微软Xbox 360和PlayStation 3。它甚至在未来计划增加闪存和Linux部署。的的部署possbilities提供很多的可能性,使用的游戏引擎或游戏引擎货币化或进一步研究。

  * Unity社区非常支持和引擎,以及编辑器是有据可查的。

* 发动机是比较容易学习和工作,并通过提供所有的工具,快速原型和迭代以及快速的脚本编译支持快速软件开发的想法。

* 可能部署的iPhone,iPad和iPod touch的iOS基本许可证与其他厂商相比,相对低廉的价格。创建机甲和坦克使用Unity3.0,C # 脚本和MonoDevelop的IDE进行开发。你可以找到一个Unity教程附录。

Unity3D的简史

   下列日期说明在2001年和2011年[16]之间的Unity引擎的演变。
 ◾2001年Unity技术在2001年开始开发自己的游戏引擎。当时的主要诱因是创建游戏,这些游戏的基础,并创造了良好的工具[1]。
 ◾2003年在2003年的公司,由此产生的引擎将是一个伟大的产品本身的。
 ◾2005年在2005年Unity1推出苹果的WWDC的舞台上。
 ◾2007Unity2.0在2007年推出,并增加了地形引擎,实时动态阴影和视频播放等等。
 ◾2008年在2008年推出Unity的iPhone和卡通网络推出FusionFall,游戏已经播放超过800万人次。

 ◾2010年在2010年Unity3.0发布了几十个新功能,如资产管理和兽光照贴图。

 ◾2011团结超过500万的开发者和60万网络播放器安装。

游戏架构

   机甲和坦克的架构组成模块和Unity的场景架构。

  主要模块

     本节介绍了最重要的模块和子系统级别上他们的关系。游戏的建筑风格,是一个对象与数据capsules.The的下面的UML组件图说明子系统及其关系网络。

游戏逻辑

    此模块管理当前玩家和AI配置倒计时timerand当前的游戏状态(暂停,等待网络回复)。

AI (人工智能(Artificial Intelligence) ,英文缩写为 AI )

    AI模块包含背后的逻辑单元,组和球员AI.The单位的AI寻路或障碍物避免使用不同的转向行为控制单元的状态。组AI管理组的行为和活动,如组寻路。更高的层次上管理播放机的所有组由播放器模块。
人工智能机器学习保存和加载它的数据使用的持久性数据模块的接口。

Persistant data持久性数据

   此模块是负责数据之间不同的游戏sessions.Among其他应可用于保存和加载,存储查找表和图寻路模块和管理学习AI的accumulateddata的机器。

Game actors游戏参与者

   游戏参与者在游戏中的地形,单位或建筑物。他们的3D模型获得通过Unity3D的渲染管线的可视化。每场比赛的演员拥有AI模块,控制它的行为。

Steering behaviours指导行为

  指导行为的计算力量,影响如何以及如何快速自主游戏代理能动,应该可以用于避障,人流或简单的寻找任务。

Pathfinding寻路

  这模块负责创建一个pathgrid,障碍物信息收集和提供各种寻路请求aninterface的。为了获得更好的性能的一些信息保存到从磁盘中加载。

Input输入

   此模块跟踪用户的输入,对其进行处理,并生成反馈。

Network网络

  网络模块是负责所有游戏演员的状态管理是保持比赛状态,在两台机器上都保持一致,以避免抖动网络单元运动网络game.Another责任。

GUI

 图形用户界面(GUI)显示所有按钮,菜单,在小地图和倒数计时器。它也负责为这些元素的功能和交互依赖与用于此目的的游戏的逻辑模块。

3D渲染

  该模块主要管理Unity3D的。场景的主摄像头确定需要渲染的对象,并把它们发送通过渲染管线。  Unity3D的 封装最渲染的细节,而且还提供了通过像素和顶点着色器的访问。

Unity场景设置

  在游戏中的每一个图表示由Unity3D的场景。下面是一个典型的场景设置在Unity层次(一)和(二)在现场窗口看起来像:

                                      

                                                                   Unity层次的地图

             

                                                                           场景视图的地图

现在所有的游戏对象从顶部面板底部进行说明。

CWalls

  这个对象包含自定义绘制墙节点和墙壁边缘。另一种是使用自定义绘制墙壁到calculatethem取决于地图的几何。

Directional light(定向光)

   此灯仅用于计算地形光照贴图。关闭之后,由于性能的原因。

Game Music(游戏音乐)

   持有游戏的主要音乐和播放现场启动。

GameController(游戏控制器)

   GameController游戏物体持有并管理所有的游戏对象,管理游戏的逻辑。它包括以下对象:

CursorController(光标控制器):

    管理光标的外观和背后的逻辑。

GameInstantiator(游戏实例化):

   这个重要的游戏对象是负责实例化其他对象需要创建非特异性顺序。

                  

                                 GameInstantiator in the Inspector

                  

                                   GameController in the Hierarchy

  GameInstantiator持有的的地图,PathCreator路径创建和管理障碍,管理球员配置和设置,是用来处理用户输入的的InputControl游戏物体,游戏场游戏物体和参考玩家游戏物体上的建筑物referenes定义了可播放的区域的地图。

 它还包含了玩家的重生点和自定义路径和墙壁的引用。

GUI

   拥有地图的所有GUI对象。

Machine Learning Controller

   此游戏物体控制的所有功能,机器学习需要。

spawn1, spawn2

  实际玩家的重生点。重生点的标志是绿色立方体“场景视图。  

HPaths

   自定义路径节点,在地图的边缘。自定义节点在场景编辑器中标记,并概述红线。     

Main Camera(主摄像机)

   现场的主摄像头和音频监听。所有的3D声音是从相机的角度观察。     

PlayArea(游戏场)

  定义实际可玩的地图区域。

Base Prefabs(基地预制)

  散落在地图上的建筑物。

Terrain(地形)

   Unity地形对象。

TestRunner

  一个物体,用于运行单元测试与Unity3D的的单位testingframework  SharpUnit 的。

MVC Pattern(MVC模式)

  Unity引擎的设计鼓励MVC(模型 - 视图 - 控制器)面向engineering.In的我的情况下,结构看起来像这样:

  

                                                               图5:MVC模式的体系结构表示

模型包含了所有的游戏对象,组件和数据文件。游戏物体的渲染器和摄像机对象的访问。

视图呈现模型和主要管理Unity3D的引擎渲染。它需要accessthe持有模型的3D模型,纹理,材质和效果。它还具有什么输入选项的影响。

控制器接收用户输入并调用模型对象上的方法反应。这是在我的游戏中所表示的输入子系统。用户能影响与他的输入的视图。

Multiplatform Development(多平台发展)

  Unity允许部署项目在不同的平台上有轻微的变化。演示和功能在很大程度上是保持取决于平台的capabilities.However,在某些领域,如在不同的设备上的输入机制存在重大分歧。

  抽象工厂设计模式应用于设计这些组件。

The Abstract Factory Pattern抽象工厂模式

                              

                                                                                     图6:抽象工厂模式

抽象工厂模式(见图6)保护客户从不同的平台上实现相同的概念在不同的APC与平台是一家集的AbstractProduct类。这些类表示一个概念,是支持所有的抽象工厂platforms.An类声明创建单一产品的经营,ConcreteFactory类代表一个特定的平台。

客户端只使用抽象工厂和抽象产品的方法,因此从一个平台的具体实施保护。

Input and Persistant Data(输入和持久性数据)

   主要有两个方面的游戏,不同的实施要求是输入机制和usageof的持久性文件的数据。  Unity3D中 不支持跨plattform数据库。这就是为什么机甲和坦克使用的持久性数据在磁盘上的二进制文件。所有平台得到了他们对于自己的能力和自己的实施,支持的文件格式。

为了保持可读性和灵活性以下适应跨平台的输入处理的抽象工厂模式:

               

                                                                      图7:输入子系统结构摘自

这仅仅是一个小所涉及的所有平台和命令,选择用于演示的摘录。

InputManager被附加到游戏物体在场景中的InputControl。它调用CommandImplementor的Execute方法的每一帧里面的更新功能。执行方法的CommandImplementor遍历所有添加的命令,检查他们的执行情况表示满意,并调用Execute方法,如果是这样。

输入子系统的组成部分的图中的抽象工厂模式:

              

iOS+Unity

     机甲和坦克被创造的过程迭代开发,这是什么原因,为什么游戏已经播放任何调整之前为iPad™。
     本章介绍和分析面临的挑战和解决方案移植机甲和坦克的iPad™。

Maximum Polygon Count(最高多边形计数)

     其中一个最明显的限制,适用于iPad™游戏的多边形数量的图形芯片能够呈现每个frame.It的横空出世,超过30万个多边形,每帧开始下降,低于25 FPS的帧率对iPad™。在3D建模软件,通过手动消除边缘和应用预定义的算法减少多边形,从一开始,某些型号甚至rebuiilding减少多边形计数后,目前在所有平台上的多边形数量是:

               

平均多边形数量大约是每单位300。如果所有的24个敌人和播放器单元的相机拍摄的,在一帧中产生的多边形的数量将是7200,平均约8500,在最坏情况下24  runners.Adding 最大4000地形的多边形(平截头体的其余部分的地形得到扑杀),最重的帧将给予约12500  GPU 多边形渲染。
Draw Call Reduction and Lights(绘制减少呼叫和灯)
即使在移动设备上不俗的表现,更重要的是每帧绘制调用的数量。一场平局发出呼叫的GPU每次绘制一个模型。如果模型有n子网格就会造成至少Ñ战平calls.Every  GUI 质地,选择飞机和健康栏添加一个调用到现场。
额外抽奖调用另一个来源是每像素光照,导致额外的绘图调用每一个光pass.That就是为什么合并成一个模型中的所有子网和型号不使用动态照明。所有的模型和地形纹理的灯光烤英寸光影烘烤计算每个纹理获取静态光源照亮奠定了光照贴图在纹理的亮度。看上去好像他们的灯光的影响,虽然没有计算模型。图8显示了几个模型,而无需光照贴图或灯光效果。

          

                                   图8:熄灭纹理材质着色器和没有灯光的烘烤模式截图

         

                                                                图9:游戏扩大统计窗口右上角的视图

这是说,可以结合Unity若干个对象,共享相同的材料制成的,在运行时,在一个单一的绘制调用的绘制在一起。这种方法被称为动态配料[18]。图9显示了66战平调用以下来源所造成的一个场景:
(GUI)图形用户界面
8绘制调用之缩小贴图按钮,,倒计时倒计时文本的+24个图斑+8号楼地图斑+1相机地图现货。总结41  GUI 造成绘制调用。
Terrain(地形)

     4画通话。其中每个质地。
Visible Models(可见模型)
   14平局呼吁。每个模型会导致比3战平调用自身的。一个用于单元网格,一个为healthbar网格和一个用于选择平面网格。低的数字都可以解释与Unity的动态配料。
Terrains(地形)
     Unity3D中没有支持的地形为iOS,直到Unity3.4发布于2011年7月[19]。为了找到最佳的解决方案机甲和坦克,地形实施的两种可供选择的方式已经过测试:模拟地形在3D程序:一个3D建模程序和地形分割成不同的部分(见图10)。分区的效果,大部分分部视锥Unity扑杀。那meansthat只有至少部分可见的段得到呈现。

                         

                                                                            图10:仿照地形突出部分

这种技术被丢弃创造新的地形,因为这个过程会非常complicatedcompared Unity的地形系统,纹理大小是非常大的或质量受到影响。  * 地形:地形移动系统移动系统是一个解决方案,可通过Unity资产商店T4M地形可以用于移动设备,并可以转换成Unity的地形。原来,这个解决方案的性能是不够的游戏。
地形最终解决方案是使用Unity地形引擎,具有非常低的质量设置。这是唯一可能后Unity3.4发布于2011年7月加入Unity地形对移动通信系统的支持。
GUI-Optimization(GUI优化)
该的Unity引擎提供两种方式来实现GUI。一种方式是使用Unity的GUI的系统UnityGUI,需要它的功能,是一个特殊的功能calledinside名为OnGUI(),即执行每帧两次和onceevery事件的。这个系统只用于主菜单,并暂停菜单,在allvalues 需要计算外OnGUI功能。
GUI纹理用于所有其他GUI元素象的GUI按钮和小地图上以维持性能。  GUI 纹理的平面图像中显示的2D和每帧渲染一次。
Script-Optimizations(脚本优化)
为了授予脚本的性能高,最便宜的方法进行跟踪与profiler.It横空出世,被称为最昂贵的方法可以通过寻路或转向行为子系统。寻路已被优化,如下文所述在AI部分。有人还提出确保昂贵的功能,如转向行为和其他AI程序不会调用每一个帧。

转载自:http://blog.csdn.net/jbjwpzyl3611421/article/details/10441681

==================Unity3D引擎架构设计======================

组件(Component)这个概念最早是在2005年《Game Programming Gems 5》的《Component Based Object Management》中接触到的,当时感觉在设计上很实用。后来,发现Unreal Engine 3的一个重要的改进就是抛弃了以前的基于纯派生关系的对象 模型 ,而转为使用 基于组件 的对象 模型 。对于这种设计思想,Unity比Unreal贯彻的更彻底——一切皆Component。

那么到底什么是“基于组件”的对象 模型 ?它能够解决什么问题?

在传统的设计中,我们一般会使用“派生”来描述对象之间的关系。子类通过派生父类,来获得父类的功能。在设计游戏对象时,会根据游戏本身的需要而为游戏对象添加各种功能支持,比如渲染,碰撞,刚体,粒子系统等等。这些通用功能为了能够为各种派生类提供服务,都必须实现到基类中。这样就导致了游戏对象基类变得非常庞大臃肿,即难使用,又难维护。

”基于组件“的对象 模型 就是把所有需要提供给游戏对象的基础功能都独立成单独的”组件模块“(Component),一个具体的游戏对象可以将它需要的功能模块组合到一起使用。所有”功能“不再是父类中的接口,而变成子对象实例,为游戏对象提供服务。这样既保证了功能代码的可重用性,又增加了整个对象体系的模块化和灵活度。

在Unity中,GameObject除了作为Component的容器之外,基本上没有其他功能。所有需要的功能都要通过组合Component来实现。脚本本身也是Component,用来在GameObject上通过控制其他Component来实现自定义的功能。虽然这些Component在物理上是完全并列的关系,但是他们之间还是会有一定的层次关系的。在设计一个游戏对象的具体功能时,组件一般会被分为三个层次。

引擎的基础组件

Unity本身提供的各种内部功能组件。比如渲染组件,物理组件,声音组件等等。这些组件实现了所有引擎提供的基础功能,会被脚本使用来组合高级功能。

模块功能脚本组件

通过脚本实现的一些相对独立的通用模块功能的组件。这类 组件的设计 是脚本可重用的关键,需要仔细分析游戏对象中哪些功能可以被独立出来成为一个可重用的功能模块组件,并且在实现上应该尽量降低与其他组件的耦合性。比如在设计一个角色游戏对象时,需要为他设计换装功能。换装功能其实就是对显示子对象进行分组管理,切换显示状态。这个功能相对独立,与其将他实现到角色中,不如独立成一个功能模块组件。角色游戏对象和其他所有需要换装功能的游戏对象都可以通过包含这个模块组件来实现换装功能。

模块功能组件之间还可能有依赖关系,也就是一个功能模块组件可能依赖与另一个功能模块组件,从而在这个组件层次上形成更多的子层次。

高层的胶水代码脚本

这些脚本用来真正将引擎基础组件和模块功能组件组合到一起实现最终游戏对象逻辑。用“胶水代码”来形容这些脚本非常的贴切,就是把所有这些子功能“粘”在一起。比如设计一个Player脚本,将所有需要的组件功能组合起来,实现一个玩家的具体游戏逻辑。因为这一层次代表的都是最高层的游戏行为控制对象,是具体的游戏逻辑的“胶水”代码,不会再为更上层提服务,所以本身的可重用性并不高。但是这些对象之间按照类型区分,往往会有一些功能上的重合,所以反而可以继续使用派生关系来实现功能的重用。比如在Character中实现所有的基础功能(这些功能又是通过组合基础组件来实现的),而Player和NPC都从Character派生,来继承所有Character的功能,并继续实现自己特殊的功能。一个功能到底应该用组件实现还是用派生实现并没有非常明确的界限,应该根据需要灵活运用。

在使用Unity的过程中,如果要实现的是demo级别的小工程,并不需要考虑很多,直接用脚本实现功能就可以了。但是如果要有效地组织复杂的工程,提高代码的重用性,充分理解和合理的利用“基于组件”的对象 模型 设计思想还是很重要的。 

2017-03-22 14:17:37 yu__jiaoshou 阅读数 2268
  • Unity3D入门到精通-(4)Unity热更新

    本次系列课程的目标是让Unity3D初学者掌握C语言,Untiy调用lua脚本深入理解uLua框架实现原理,并根据项目的特点实现相应的热更新方案。 适合对象:Unity初学开发者,Unity中级开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    2211 人正在学习 去看看 张刚

Unity3D - UI摄像机、场景摄像机协同工作原理 :

UI摄像机和场景摄像机分别属于两个渲染层(Layer),所以它们之间的渲染互不干扰 , 将摄像机深度(depth)控制好 , 使得 UI摄像机高于场景摄像机 , UI永远位于场景上层 .

2016-05-26 11:11:06 woaini454186694 阅读数 2707
  • Unity3D入门到精通-(4)Unity热更新

    本次系列课程的目标是让Unity3D初学者掌握C语言,Untiy调用lua脚本深入理解uLua框架实现原理,并根据项目的特点实现相应的热更新方案。 适合对象:Unity初学开发者,Unity中级开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    2211 人正在学习 去看看 张刚

Unity3D工具、Mono工具、内部脚本工作原理以及跨平台特性


1、几个概念的理解:

Unity3D主要包括两个部分:Unity Engine和Unity Editor。提供了UnityEngine.dll和UnityEditor.dll两个动态库。
Unity Engine:C/C++编写,由平台相关代码,图形API、物理引擎、灯光、网络层接口等组成,编译为UnityEngine.dll,各平台不同,用户Shader代码也属于这一层的内容;
Unity Editor:IDE工具,大部分是由C#编写,插件也是用C#编写(调用UnityEditor.dll开发),用户脚本可用C#/JS/Boo编写,项目代码最后由Mono编译;
Mono运行环境:Novell公司开发的跨平台·NET运行环境。功能是编译工程以及提供不同平台的CLR运行时。对于Android平台,首先编译输出为dll(即IL),游戏启动时Mono运行时再将用户dll和UnityEngine.dll等编译为JIT格式运行;对于IOS平台,由于不允许运行时生成Native Code,只能一次性将UnityEngine.dll和用户脚本等编译为Full AOT格式存储。

JIT(Just-in-Time compilation,即时编译)

AOT(Ahead-of-Time,提前编译或静态编译)

上面说了,在IOS平台,不能再运行时生成Native code,为了绕过苹果公司的这个机制,可以使用Lua语言来实现热更新。


2、Unity3D程序以及内部脚本工作原理:
由上面介绍可知,Unity程序调用的层次关系是:

脚本(C#/JS/Boo)/UnityEditor/Unity Plugin --> 

UnityEngine(C/C++) --> 

图形API(OpenGL/DirectX/CG/Shader等)/物理引擎(Nvidia的PhysX)/灯光(Autodesk的Beast/Enlighten)/网络层(UNET) --> 

底层代码(如操作系统内核、汇编等) --> 

硬件

3、Unity3D跨平台特性:
这里的上帝是Mono,它为Unity游戏提供了.Net框架。针对不同平台的编译打包,都会把Mono运行时打包进去,当执行用户脚本的时候,就是由它来解析,从而达到跨平台的效果。

2013-08-28 15:32:56 jbjwpzyl3611421 阅读数 35879
  • Unity3D入门到精通-(4)Unity热更新

    本次系列课程的目标是让Unity3D初学者掌握C语言,Untiy调用lua脚本深入理解uLua框架实现原理,并根据项目的特点实现相应的热更新方案。 适合对象:Unity初学开发者,Unity中级开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    2211 人正在学习 去看看 张刚

体系结构

   为了更好地理解游戏的软件架构和对象模型获得更好的外观仅有一名Unity3D的游戏引擎和编辑器是非常有用的它的主要原则

Unity3D 引擎

   Unity3D的一个屡获殊荣的工具,用于创建交互式3D应用程序多个平台.Unity3D游戏引擎编辑器该引擎包含的软件组件游戏的研究与开发最常见的和经常性任务发动机涵盖的主题包括声音,图形,物理和网络功能该引擎支持C#Boo和JavaScript脚本编程

另一个部分是Unity编辑,作为脚本和其他组件包含游戏场景设置和游戏预览窗口(见图4)分层对象检查项目面板集成开发环境它还配备了几个多语言脚本编辑器和一个独特的预制装配系统,将在后面解释

 

                                                          图4:Unity3D编辑

 

有几个Unity许可证。Unity基本功能有限的免费PCMACWebdevelopment.Other平台完整的功能集[15]需要购买额外的许可证

虽然有很多免费软件和专有替代游戏引擎虚幻引擎C4引擎选择了Unity的原因如下

*可以部署在Windows,Mac OSXWeb浏览器,Wii游戏机iPhone,iPad的Android,微软Xbox 360和PlayStation 3它甚至在未来计划增加闪存Linux部署部署possbilities提供很多的可能性使用游戏引擎游戏引擎货币化进一步研究。

 *Unity社区非常支持引擎,以及编辑器是有据可查的

*发动机是比较容易学习和工作通过提供所有的工具快速原型和迭代以及快速脚本编译支持快速软件开发的想法

*可能部署的iPhone,iPad和iPod touch的iOS基本许可证其他厂商相比相对低廉的价格创建机甲坦克使用Unity3.0C#脚本和MonoDevelop的IDE进行开发你可以找到一个Unity教程附录

Unity3D的简史

 下列日期说明2001和2011年[16]之间的Unity引擎的演变
 ◾2001年Unity技术在2001年开始开发自己的游戏引擎当时主要诱因创建游戏这些游戏的基础创造了良好的工具[1]。
 ◾2003在2003年公司,由此产生的引擎将是一个伟大产品本身的
 ◾2005在2005年Unity1推出苹果的WWDC的舞台上
 ◾2007Unity2.0在2007年推出增加地形引擎实时动态阴影和视频播放等等
 ◾2008在2008年推出UnityiPhone卡通网络推出FusionFall,游戏已经播放超过800万人次

 ◾20102010年Unity3.0发布几十个功能,如资产管理和光照贴图

 ◾2011团结超过500开发者和60网络播放器安装。

游戏架构

 机甲坦克架构组成模块和Unity场景架构

 主要模块

    本节介绍了最重要的模块子系统级别他们关系。游戏的建筑风格是一个对象数据capsules.The下面的UML组件图说明子系统及其关系网络

 

游戏逻辑

   此模块管理当前玩家AI配置倒计时timerand当前的游戏状态暂停等待网络回复

AI(人工智能(Artificial Intelligence) ,英文缩写为AI

   AI模块包含背后的逻辑单元球员AI.The单位AI寻路或障碍物避免使用不同转向行为控制单元状态。AI管理组的行为和活动寻路更高的层次上管理播放机的所有播放器模块

人工智能机器学习保存和加载它的数据使用持久性数据模块的接口

Persistant data持久性数据

   此模块是负责数据之间不同的游戏sessions.Among其他应可用于保存和加载存储查找表和寻路模块管理学习AIaccumulateddata机器

Game actors游戏参与者

  游戏参与者在游戏中地形,单位或建筑物他们的3D模型获得通过Unity3D的渲染管线的可视化每场比赛演员拥有AI模块控制它的行为

Steering behaviours指导行为

  指行为计算力量,影响如何以及如何快速自主游戏代理能动,应该可以用于避障,人流简单寻找任务

Pathfinding寻路

  模块负责创建一个pathgrid障碍物信息收集提供各种寻路请求aninterface为了获得更好的性能一些信息保存到从磁盘中加载

Input输入

  此模块跟踪用户的输入对其进行处理生成反馈。

Network网络

  网络模块负责所有游戏演员状态管理保持比赛状态在两台机器上都保持一致以避免抖动网络单元运动网络game.Another责任

GUI

 图形用户界面(GUI)显示所有按钮,菜单在小地图倒数计时器它也负责这些元素的功能交互依赖用于此目的游戏逻辑模块

3D渲染

  该模块主要管理Unity3D的场景的主摄像头确定需要渲染的对象并把它们发送通过渲染管线Unity3D的封装渲染细节而且还提供了通过像素和顶点着色器访问

Unity场景设置

  在游戏中一个表示Unity3D的场景下面是一个典型的场景设置在Unity层次(一)(二)现场窗口看起来像

                                     

                                                                   Unity层次的地图

            

                                                                          场景视图的地图

现在所有的游戏对象顶部面板底部进行说明。

CWalls

  这个对象包含自定义绘制节点和墙壁边缘一种使用自定义绘制墙壁calculatethem取决于地图的几何

Directional light(定向光)

  此灯仅用于计算地形光照贴图关闭之后由于性能的原因

Game Music(游戏音乐)

  持有游戏的主要音乐和播放现场启动

GameController(游戏控制器)

  GameController游戏物体持有管理所有的游戏对象管理游戏的逻辑包括以下对象

CursorController(光标控制器):

   管理光标的外观和背后的逻辑

GameInstantiator(游戏实例化):

   这个重要游戏对象负责实例其他对象需要创建非特异性顺序

                  

                                 GameInstantiator in the Inspector

                  

                                   GameController in the Hierarchy

  GameInstantiator持有地图PathCreator路径创建和管理障碍管理球员配置设置是用来处理用户输入InputControl游戏物体游戏场游戏物体和参考玩家游戏物体上的建筑物referenes定义了播放区域的地图

 它还包含玩家的重生点和自定义路径和墙壁引用

GUI

  拥有地图的所有GUI对象

Machine Learning Controller

   游戏物体控制的所有功能机器学习需要

spawn1, spawn2

  实际玩家的重生点重生点的标志是绿色立方体“场景视图  

HPaths

   定义路径节点在地图边缘定义节点场景编辑标记并概述红线     

Main Camera(主摄像机)

   现场主摄像头和音频监听所有的3D声音相机的角度观察     

PlayArea(游戏场)

  定义实际可玩的地图区域

Base Prefabs(基地预制)

  散落在地图上的建筑物

Terrain(地形)

   Unity地形对象

TestRunner

  一个物体,用于运行单元测试Unity3D的单位testingframeworkSharpUnit

MVC Pattern(MVC模式)

  Unity引擎的设计鼓励MVC模型 - 视图 -控制器面向engineering.In我的情况下结构看起来像这样

 

                                                              图5:MVC模式体系结构表示

模型包含了所有的游戏对象组件和数据文件游戏物体渲染器和摄像机对象访问

视图呈现模型和主要管理Unity3D的引擎渲染它需要accessthe持有模型3D模型,纹理材质和效果它还具有什么输入选项影响

控制器接收用户输入并调用模型对象方法反应这是在我的游戏中所表示输入子系统用户能影响输入视图

Multiplatform Development(多平台发展)

  Unity允许部署项目在不同的平台上轻微变化。演示和功能在很大程度上是保持取决于平台的capabilities.However在某些领域在不同的设备上输入机制存在重大分歧

  抽象工厂设计模式应用于设计这些组件

The Abstract Factory Pattern抽象工厂模式

                             

                                                                                    图6:抽象工厂模式

抽象工厂模式(见图6保护客户不同平台上实现相同的概念不同APC与平台是一家集AbstractProduct这些类表示一个概念,是支持所有抽象工厂platforms.An声明创建单一产品经营ConcreteFactory代表一个特定平台

客户端只使用抽象工厂抽象产品方法,因此一个平台的具体实施保护

Input and Persistant Data(输入和持久性数据)

   主要有两个方面的游戏不同的实施要求是输入机制和usageof持久性文件数据Unity3D中不支持plattform数据库这就是为什么机甲坦克使用持久性数据在磁盘上二进制文件所有平台得到了他们对于自己的能力自己实施支持的文件格式

 

为了保持可读性和灵活性以下适应跨平台的输入处理抽象工厂模式

              

                                                                     图7:输入子系统结构摘自

 

这仅仅是一个所涉及的所有平台和命令,选择用于演示的摘录

InputManager附加到游戏物体在场景中InputControl调用CommandImplementorExecute方法的每一帧里面的更新功能执行方法CommandImplementor遍历所有添加命令,检查他们执行情况表示满意,并调用Execute方法,如果是这样

 

输入子系统组成部分的抽象工厂模式

             

iOS+Unity

     机甲坦克被创造的过程迭代开发,这是什么原因为什么游戏已经播放任何调整之前为iPad

     本章介绍分析面临的挑战和解决方案移植机甲和坦克的iPad

Maximum Polygon Count(最高多边形计数)

     其中一个最明显的限制,适用于iPad™游戏的多边形数量的图形芯片能够呈现每个frame.It横空出世超过30多边形,每帧开始下降,低于25 FPS的帧率对iPad在3D建模软件通过手动消除边缘和应用预定义的算法减少多边形从一开始某些型号甚至rebuiilding减少多边形计数,目前在所有平台上多边形数量是:

              

平均多边形数量大约是每单位300如果所有的24个敌人和播放器单元的相机拍摄的在一帧中产生多边形的数量将是7200,平均约8500在最坏情况下24runners.Adding最大4000地形多边形平截头体的其余部分的地形得到扑杀,最重的将给予12500GPU多边形渲染

Draw Call Reduction and Lights(绘制减少呼叫灯)


即使在移动设备上不俗的表现,更重要的每帧绘制调用的数量一场平局发出呼叫GPU每次绘制一个模型如果模型有n子网格就会造成至少Ñ战平calls.EveryGUI质地,选择飞机和健康添加一个调用到现场

额外抽奖调用另一个来源像素光照,导致额外绘图调用一个pass.That就是为什么合并成一个模型中所有子网型号不使用动态照明所有模型和地形纹理的灯光英寸光影烘烤计算每个纹理获取静态光源照亮奠定了光照贴图纹理的亮度看上去好像他们的灯光的影响虽然没有计算模型图8显示了几个模型,而无需光照贴图灯光效果

         

                                  图8:熄灭纹理材质着色器没有灯光烘烤模式截图

        

                                                                9:游戏扩大统计窗口右上角视图

这是可以结合Unity若干个对象共享相同的材料制成在运行时在一个单一的绘制调用的绘制在一起这种方法被称为动态配料[18]。图9显示了66战平调用以下来源所造成的一个场景

(GUI)图形用户界面


8绘制调用之缩小贴图按钮,,倒计时倒计时文本+24个+8号楼地图+1相机地图现货总结41GUI造成绘制调用

Terrain(地形)


     4通话其中每个质地

Visible Models(可见模型)

   14平局呼吁每个模型会导致比3战平调用自身的一个用于单元一个healthbar网格和一个用于选择平面网格数字都可以解释Unity的动态配料

Terrains(地形)


     Unity3D中没有支持地形为iOS直到Unity3.4发布于2011年7月[19]。为了找到最佳的解决方案机甲坦克,地形实施两种可供选择的方式已经过测试模拟地形在3D程序一个3D建模程序地形分割成不同的部分见图10)分区的效果大部分分部视锥Unity扑杀meansthat只有至少部分可见得到呈现

                         

                                                                            图10:仿照地形突出部分

这种技术被丢弃创造新的地形,因为这个过程会非常complicatedcompared Unity地形系统纹理大小非常大的质量受到影响*地形地形移动系统移动系统一个解决方案,通过Unity资产商店T4M地形可以用于移动设备可以转换成Unity的地形原来,这个解决方案的性能是不够游戏

地形最终解决方案使用Unity地形引擎具有非常低的质量设置是唯一可能Unity3.4发布于2011年7月加入Unity地形对移动通信系统支持

GUI-Optimization(GUI优化)


Unity引擎提供两种方式来实现GUI一种方式是使用Unity的GUI系统UnityGUI需要它的功能一个特殊的功能calledinside名为OnGUI()执行每帧两次onceevery事件这个系统只用于主菜单,并暂停菜单allvalues​​需要计算OnGUI功能

GUI纹理用于所有其他GUI元素GUI按钮和小地图上以维持性能GUI纹理平面图像中显示的2D和每帧渲染一次

Script-Optimizations(脚本优化)


为了授予脚本的性能便宜的方法进行跟踪profiler.It横空出世被称为最昂贵方法可以通过寻路转向行为子系统寻路已被优化如下文所述在AI部分有人还提出确保昂贵的功能,如转向行为和其他AI程序不会调用每一个帧

2018-11-06 10:25:38 vimfung 阅读数 134
  • Unity3D入门到精通-(4)Unity热更新

    本次系列课程的目标是让Unity3D初学者掌握C语言,Untiy调用lua脚本深入理解uLua框架实现原理,并根据项目的特点实现相应的热更新方案。 适合对象:Unity初学开发者,Unity中级开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    2211 人正在学习 去看看 张刚

1. 关于Unity3D

Unity3D(以下简称U3D)是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

作为一款跨平台开发工具,难免会与原生平台进行一些交互操作来完成一些特定的平台功能。例如:你需要直接操作iOS的IAP来实现游戏中的内付费功能;甚至一些第三方SDK没有提供U3D版本的情况下,你会直接在原生系统平台调用其提供接口等等。

下面将为大家介绍,在U3D下如何实现与iOS系统的交互工作,来满足一些需要借助原生系统的功能需求。

2. From U3D to iOS

2.1 实现原理

由于U3D无法直接调用Objc或者Swift语言声明的接口,幸好U3D的主要语言是C#,因此可以利用C#的特性来访问C语言所定义的接口,然后再通过C接口再调用ObjC的代码(对于Swift代码则还需要使用OC桥接)。例如,有如下C语言方法:

void nativeMethod ()
{
  NSLog(@"------- objc method call...\n");
}

在C#中则可以像下面代码一样进行引入和调用:

using System.Runtime.InteropServices;

[DllImport("__Internal")]
internal extern static void nativeMethod();

其中DllImport为一个Attribute,目的是通过非托管方式将库中的方法导出到C#中进行使用。而传入"__Internal"则是表示这个是一个静态库或者是一个内部方法。通过上面的声明,这个方法就可以在C#里面进行调用了。如:

public class Sample
{
  public void test ()
  {
    nativeMethod();
  }
}

2.2 实现步骤

下面通过一个拼接字符串的例子来说明怎么样从U3D中传入两个字符串到iOS中,然后由iOS拼接后通过NSLog输出结果:

  1. 首先新建test.mtest.h两个文件。分别写入如下内容:
/// test.h

extern "C"
{
  extern void outputAppendString (char *str1, char *str2);
}
/// test.m
#import <Foundation/Foundation.h>

void outputAppendString (char *str1, char *str2)
{
  NSString *string1 = [[NSString alloc] initWithUTF8String:str1];
  NSString *string2 = [[NSString alloc] initWithUTF8String:str2];
  
  NSLog(@"###%@", [NSString stringWithFormat:@"%@ %@", string1, string2]);
}
  1. 然后将上面的两个文件放到U3D项目的Assets目录中。如图:

放入U3D项目

  1. 分别选择test.htest.m文件,在Inspector面板中去掉Any Platforms的勾选,然后保留iOS这一项选中。如图:

设置平台插件

  1. 新建一个叫Sample的C#脚本文件,并在这个文件中写入c接口的声明,如:
public class Sample : MonoBehaviour 
{
	//引入声明
	[DllImport("__Internal")]
	static extern void outputAppendString (string str1, string str2);
}
  1. 在Start方法中调用该方法,如:
void Start () 
{
	#if UNITY_IPHONE	
	outputAppendString("Hello", "World");
	#endif
}

注意:对于指定平台的方法,一定要使用预处理指令#if来包括起来。否则在其他平台下面执行会导致异常。

  1. 拖动Sample脚本到场景的Main Camera对象中,让脚本进行挂载。

挂载脚本

  1. 使用快捷键Command+Shift+B(或者点击菜单File -> Build Settings)调出Build Settings窗口,将项目导出为iOS项目。如图:

导出iOS项目

  1. 打开导出的iOS项目,先检查之前创建的test.mtest.h是否已经导出到项目中。如图:

检查文件

  1. 编译运行应用,可以看到控制台中会输出合并后的字符串信息,如:
2018-01-22 16:17:15.143166+0800 ProductName[29211:4392515] ###Hello World

3. From iOS to U3D

对于如何从iOS中调用U3D的接口,分为两种办法:一种是通过UnitySendMessage方法来调用Unity所定义的方法。另一种方法则是通过入口参数,传入一个U3D的非托管方法,然后调用该方法即可。两种方式的对比如下:

UnitySendMessage方式 非托管方法方式
接口声明固定,只能是void method(string message) 接口灵活,可以为任意接口。
不能带有返回值 可以带返回值
必须要挂载到对象后才能调用。 可以不用挂载对象,但需要通过接口传入该调用方法

下面将一一讲述两种方式的实现。

3.1 UnitySendMessage

  1. 基于上面调用iOS接口的例子,在Sample.cs中增加一个callback方法。如:
void callback (string resultStr)
{
	Debug.LogFormat ("result string = {0}", resultStr);
}
  1. 由于项目已经挂载Sample.cs到Main Camera中,这就不用再进行挂载。然后打开test.m文件,在outputAppendString方法中调用callback方法,并将组合字符串返回给U3D。如:
void outputAppendString (char *str1, char *str2)
{
    NSString *string1 = [[NSString alloc] initWithUTF8String:str1];
    NSString *string2 = [[NSString alloc] initWithUTF8String:str2];
    
    NSString *resultStr = [NSString stringWithFormat:@"%@ %@", string1, string2];
    NSLog(@"###%@", resultStr);
    
    UnitySendMessage("Main Camera", "callback", resultStr.UTF8String);
}
  1. 导出iOS项目,编译运行看执行结果。
2018-01-22 17:47:00.137259+0800 ProductName[29561:4429040] ###Hello World
Setting up 1 worker threads for Enlighten.
  Thread -> id: 170cb3000 -> priority: 1 
result string = Hello World
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

3.2 非托管方法

  1. Sample.cs中建立一个delegate声明,并使用UnmanagedFunctionPointer特性来标识该delegate是非托管方法。代码如下:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ResultHandler(string resultString);

其中的CallingConvention.Cdel为调用时转换为C声明接口。

  1. 然后声明一个静态方法,并使用MonoPInvokeCallback特性来标记为回调方法,目的是让iOS中调用该方法时可以转换为对应的托管方法。如:
[MonoPInvokeCallback(typeof(ResultHandler))]
static void resultHandler (string resultStr)
{
	
}

注意:MonoPInvokeCallback特性参数是上一步中定义的非托管delegate。方法的声明一定要与delegate定义一致,并且必须为static进行修饰(iOS不支持非静态方法回调),否则会导致异常。

  1. 打开test.m文件,定义一个新的接口,如:
typedef void (*ResultHandler) (const char *object);

void outputAppendString2 (char *str1, char *str2, ResultHandler resultHandler)
{
    NSString *string1 = [[NSString alloc] initWithUTF8String:str1];
    NSString *string2 = [[NSString alloc] initWithUTF8String:str2];
    
    NSString *resultStr = [NSString stringWithFormat:@"%@ %@", string1, string2];
    NSLog(@"###%@", resultStr);
    
    resultHandler (resultStr.UTF8String);
}

上面代码可见,在C中需要定义一个与C#的delgate相同的函数指针ResultHandler。然后新增的outputAppendString2方法中多了一个回调参数resultHandler。这样就能够把C#传入的方法进行调用了。

  1. 回到Sample.cs文件,定义outputAppendString2的声明。
[DllImport("__Internal")]
static extern void outputAppendString2 (string str1, string str2, IntPtr resultHandler);

注意:回调方法的参数必须是IntPtr类型,表示一个函数指针。

  1. Start方法中调用outputAppendString2,并将回调方法转换为IntPtr类型传给方法。如:
ResultHandler handler = new ResultHandler(resultHandler);
IntPtr fp = Marshal.GetFunctionPointerForDelegate(handler);
outputAppendString2 ("Hello", "World", fp);

上面代码使用MarshalGetFunctionPointerForDelegate来获取resultHandler的指针。

  1. 导出iOS项目,编译运行。
2018-01-22 19:02:31.339317+0800 ProductName[29852:4459349] ###Hello World
result string = Hello World
Sample:outputAppendString2(String, String, IntPtr)
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

4. 类型传递

对于基础类型数据(如:int、double、string等)是可以直接从U3D中传递给iOS的。具体对应关系如下表所示:

U3D iOS
short short
int int
long long long
bool bool
char char
string char *
struct struct
byte[] void *
IntPtr void *

注意

  • 引用型数据不能直接从U3D传给iOS。如果需要传递这样的类型,可以考虑将对象序列化成byte数组,然后在iOS中进行反序列化将其还原回来。
  • 对于string类型,会自动转换为c语言中的char *。但是由于C#中的string是托管类型,因此char *是无法直接转换为string的,所以不要直接在返回值中返回char *类型。下一节会针对返回值进行详细的说明。
  • struct类型数据中不能包含引用型数据,否则在调用接口时会报告类似下面的提示:
MarshalDirectiveException: Cannot marshal field 't' of type 'TestStructType': Reference type field marshaling is not supported.

4.1 关于Marshal

Marshal类型主要是用于将C#中托管和非托管类型进行一个转换的桥梁。其提供了一系列的方法,这些方法包括用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法等。

本质上U3D与iOS的交互过程就是C#与C的交互过程,所以Marshal就成了交互的关键,因为C#与C的交互正正涉及到托管与非托管代码的转换。下面将举例说明,如何将一个C#的引用类型转换到对应的OC类型。

  1. 首先在C#中声明一个类型Person
class Person
{
	public string name;
	public int age;
}
  1. 在C中声明一个接口printPersonInfo用于打印传递过来的Person信息,如:
void printPersonInfo(void *personData);
  1. 在C#中声明此接口
[DllImport("__Internal")]
static extern void printPersonInfo (IntPtr personData);
  1. 创建一个Person的实例,然后将其序列化成byte数组,这里使用到对象序列化的一些知识。
Person person = new Person();
person.name = "vimfung";
person.age = 18;

List<byte> buf = new List<byte>();

//写入name
byte[] bytes = BitConverter.GetBytes (person.name.Length);
if (BitConverter.IsLittleEndian)
{
	Array.Reverse (bytes);
}
buf.AddRange (bytes);
buf.AddRange (Encoding.UTF8.GetBytes (person.name));

//写入age
bytes = BitConverter.GetBytes (person.age);
if (BitConverter.IsLittleEndian)
{
	Array.Reverse (bytes);
}
buf.AddRange(bytes);

byte[] bufBytes = buf.ToArray();
  1. 将byte数组通过Marshal类转换为IntPtr类型,并传入给C接口。
//转换成功IntPtr
IntPtr personData = Marshal.AllocHGlobal(bufBytes.Length);
Marshal.Copy(bufBytes, 0, personData, bufBytes.Length);

printPersonInfo(personData);

Marshal.FreeHGlobal(personData);

注意:Marshal申请的内存不是自动回收的,因此调用后需要通过显示方法FreeHGlobal调用释放。

  1. 回到C代码中,并实现其内部处理逻辑,如:
void printPersonInfo(void *personData)
{
    int offset = 0;
    
    //获取name
    int nameLen = (((unsigned char *)personData) [offset] << 24)
    | (((unsigned char *)personData) [offset + 1] << 16)
    | (((unsigned char *)personData) [offset + 2] << 8)
    | (((unsigned char *)personData) [offset + 3]);
    offset += 4;
    
    char *nameBuf = malloc(sizeof(char) * (nameLen + 1));
    memset(nameBuf, 0, nameLen);
    memcpy(nameBuf, (char *)personData + offset, nameLen);
    offset += nameLen;
    NSLog(@"person name = %s", nameBuf);
    
    //获取age
    int age = (((unsigned char *)personData) [offset] << 24)
    | (((unsigned char *)personData) [offset + 1] << 16)
    | (((unsigned char *)personData) [offset + 2] << 8)
    | (((unsigned char *)personData) [offset + 3]);
    NSLog(@"person age = %d", age);
}
  1. 导出iOS项目,编译运行可以看到日志里面的输出结果
2018-01-29 14:38:56.378376+0800 ProductName[8584:1163121] person name = vimfung
2018-01-29 14:38:56.378509+0800 ProductName[8584:1163121] person age = 18

5. 返回值

除了基础类型中的数值类型可以直接从iOS中返回给U3D外,其他的类型是不能直接进行返回的,其中理由也很简单,因为非托管类型不能直接转换成托管类型。如果你想直接返回一个字符串给U3D,那么在运行时就会产生异常,因为转换成托管类型后他的内存由系统管理,一旦对象销毁他就会被释放内存,但它并不知道非托管模式下它是否被释放。

为了解决返回值的问题,其实可以借助上面提到的Marshal类型配合序列化的方式来进行返回值的返回:

  1. 先定义C代码中的接口
void* returnString(int *len)
{
    NSString *retStr = @"Hello World";
    *len = (int)retStr.length;
    
    char *nameBuffer = malloc(sizeof(char) * (retStr.length + 1));
    memcpy(nameBuffer, retStr.UTF8String, retStr.length);
    return nameBuffer;
}
  1. 在C#中声明该接口
[DllImport("__Internal")]
static extern IntPtr returnString (out int len);
  1. 调用该接口,并解析返回参数值
int strLen = 0;
IntPtr stringData = returnString(out strLen);
if (strLen > 0)
{
	byte[] buffer = new byte[strLen];
	Marshal.Copy(stringData, buffer, 0, strLen);
	Marshal.FreeHGlobal(stringData);

	string str = Encoding.UTF8.GetString(buffer);
	Debug.Log(str);
}

UNITY3D NETWORK

阅读数 774

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