我要发帖 回复

管理员

327

主题

4043

积分

15

专家分

兴趣点(最多三项):

视景仿真
地形仿真
高层游戏引擎

私信
发表时间 : 2009-3-23 19:28:13 | 浏览 : 3005    评论 : 3
<P>Unity是一个以Mono为基础的游戏开发环境,能同时支持三种脚本语言,包括C#、Javascript和Boo(类似Python)。</P>
<P>由于Unity的开发工具暂时只有Mac的版本,所以暂时未能测试。但是它有很详细的文档,看上来很易用,所以就从文字上学习它的Script使用方式。</P>
<P>跟据一些Tutorial及参考手册,我用Graphviz画了一个(我认为)最核心的UML类别图:<BR> d.jpg </P>
<P>&nbsp;</P>
<P>从这个类别图我们可以理解它的结构,及如何把一些常用功能映像至这系统里,以下分节讨论。</P>
<P>&nbsp;</P>
<P>GameObject和Component</P>
<P><BR>Unity的执行环境里,会有一个场境(Scene)。这个场境包含一个GameObject对象的层阶(Hierarchy)。</P>
<P>这个GameObject类别只是一个包容器,本身没有其他功能。用户需要为GameObject加入各种Component对象来定义它的行为,而不是透过继承(inherit)GameObject来加入行为。</P>
<P>一个对象可拥有多个Component对象,但有一些Component类别只可以在一个GameObject中有一个实体(instance)。</P>
<P><BR>MonoBehavior</P>
<P>我最感兴趣的,是使用者如何自行定义行为来做出不同的Gameplay。在Unity中,程序员编写的Script,其实也是Component的一种,所有的Script都会继承自MonoBehavior类别。以下是一个简单例子:</P>
<P>varspeed=5.0;</P>
<P>functionUpdate(){<BR>varx=Input.GetAxis("Horizontal")*Time.deltaTime*speed;<BR>varz=Input.GetAxis("Vertical")*Time.deltaTime*speed;<BR>transform.Translate(x,0,z);<BR>}</P>
<P>把这个Script加进一个GameObject的话(成为该GameObject的一个Component),Runtime会在每帧呼叫Update(),玩家就可以用上下左右键控制那个GameObject在水平方向移动。。</P>
<P><BR>Transform</P>
<P>每个能在三维空间里的GameObject都会有TransformComponent(未有详细看是否有一些GameObject可以省郄Transform,例如一个用来定义一个游戏任务的GameObject)。Transform包括位置、旋转及缩放。</P>
<P>之前的例子已用了transformcomponent,不过它其实是Object类别的一个shortcut,这shortcut其实等同:</P>
<P>GetComponent(Transform).Translate(x,0,z)</P>
<P><BR>Component的连结</P>
<P>在ScriptTutorial里的例子是写一个Follow的行为,拥有这个Component的GameObject会自动追踪(面对着)一个目标对象:</P>
<P>vartarget:Transform;</P>
<P>functionUpdate(){<BR>transform.LookAt(target);<BR>}</P>
<P>这个Script暴露了一个target变量(应当作成员变量吧),用户可以把其他对象的变量assign至这个变量。这assignment有两种方法实现,其一是利用Unity的GUI工具把一个Component实体的变量(如Transform)drag-and-drop至这个Component实体的target变量,而另一个方法是写代码:</P>
<P>varnewTarget=GameObject.Find("Cube").transform;<BR>GetComponent(Follow).target=newTarget;</P>
<P>用代码就可以这样动态改变这些Component之间的联结方式。或者另一个说法是,GUI工具是可以设定起始的联结,而Script可以在执行期改变这些联结。</P>
<P><BR>渲染</P>
<P>一个可被渲染的GameObject需要有以几个Components,以Mesh为例:</P>
<P>1.MeshFilter:用来找出现时的Mesh对象</P>
<P>2.MeshRenderer:用来渲染Mesh的Component,会参考一个material对象</P>
<P>要注要Mesh和Material对象并非Component,它们是继承自Object的。但是你仍然可以去动态改变它们。但由于它们不是Component,所以可以被分享,例如多个GameObject的MeshRenderer都参考到同一个Material。一个Component实体只属于一个GameObject(所以在UML中我用黑色钻石表示Composition)。</P>
<P>而Light和Camera则是Component,这意未着可以简单的设定联结。</P>
<P>&nbsp;</P>
<P>分析</P>
<P>Unity的Script对象模型是以Component为基础的。透过把Component实体加入GameObject实体来组合不同功能的对象,而Component实体之间可以建立联结。</P>
<P>这种方式不需要透过继承(inheritance),而是透过聚合(aggregation)加入对象的功能和行为。使用聚合的好处是不会产生复杂的继承层阶,亦可以动态改变聚合的结构(例如在执行期加入或移除Component)。</P>
<P>有一些细节我暂时未清楚,例如多个Component在一个GameObject中的执行次序如何设定;联结会否有cylic的问题等等。可能要拿到软件再试用才可以知道。</P>
<P>&nbsp;</P>
<P>结语</P>
<P>Unity的脚本系统给我的感觉是使用非常简单。透过很少的代码就能写一些行为,甚至把行为组合到对象中。但是,通常容易的东西都会有相对的缺点,例如在效能上或是Scalability上。后者可能是一个很大的问题,当游戏规模扩大,Component和联结就会变成一个很复杂的graph,由于连结是发生于执行期(而非静态),可能要作改动会变得困难。换句话说,就是改几十个类别容易,改它们的几千个实体就会很困难。</P>
<P>软件设计世界里当然没有银子弹,每个方案都适合不同的情况。我认为Unity的一个设计目标是容易使用,就是像Virtools之流,可以给没有程序底子的人做游戏,相对来说做比较复杂的项目可能会遇到许多问题。但参考一下总可以给予对事物新的观点,或分析另一个科案的强劲之处。<BR></P>

最近VR访客

牛模王 评论于2009-4-28 11:06:55
分析的非常到位
zksuyu 评论于2009-5-16 17:08:47
你觉得你讲的这些简单的像小学生的数学,但对于做三维设计的同行们来说,简直就是天书~~~
spritez 评论于2009-5-17 18:55:22
这个分析不错!是个设计方法问题。所有做它的都应该需要了解,不至于最后手忙脚乱.

手机版|VR开发网 ( 津ICP备18009691号 ) 统计 网安备12019202000257

GMT+8, 2020-10-22 11:23 AM

返回顶部