解构Unity的腳本物件模型

         是一个以 Mono 为基础的游戏开发环境,能同时支持三种脚本语言,包括 C#、Javascript 和 Boo (类似 Python)。由于 Unity 的开发工具暂时只有 Mac 的版本 (2010年2月25日更新: 现时已有Windows版本,而且有免费授权版,另外因为Unity iPhone版的出现使Unity的使用者大增),所以暂时未能测试。但是它有很详细的文档,看上来很易用,所以就从文字上学习它的 Script 使用方式。跟据一些 Tutorial及参考手册,我用 Graphviz 画了一个 (我认为) 最核心的 UML 类图:



        从这个类图我们可以理解它的结构,及如何把一些常用功能映射至这系统里,以下分节讨论。


GameObject 和 Component


        的执行环境里,会有一个场境 (Scene)。这个场境包含一个 GameObject对象的层阶 (Hierarchy)。这个 GameObject类只是一个容器,本身没有其他功能。使用者需要为 GameObject加入各种 Component对象来定义它的行为,而不是透过继承 (inherit) GameObject来加入行为。一个对象可拥有多个 Component对象,但有一些 Component类别只可以在一个 GameObject中有一个实例 (instance)


MonoBehavior

        我最感兴趣的,是使用者如何自行定义行为来做出不同的 Gameplay。在 Unity中,程式员编写的 Script,其实也是 Component的一种,所有的 Script都会继承自 MonoBehavior类别。以下是一个简单例子


var speed = 5.0; 
  
function Update () { 
    var x = Input.GetAxis("Horizontal") * Time.deltaTime * speed; 
    var z = Input.GetAxis("Vertical") * Time.deltaTime * speed; 
    transform.Translate(x, 0, z); 
}

        把这个 Script加进一个 GameObject的话 (成为该 GameObject的一个 Component)Runtime会在每帧呼叫 Update(),玩家就可以用上下左右键控制那个 GameObject在水平方向移动。。


Transform

         每个能在三维空间里的 GameObject都会有 TransformComponent (未有详细看是否有一些 GameObject可以省郤 Transform,例如一个用来定义一个游戏任务的 GameObject)Transform包括平移、旋转及缩放。之前的例子已用了 Transform Component,不过它其实是 Object类别的一个简写,这简写其实等同


GetComponent(Transform).Translate(x, 0, z)

Component 的连结

       在 Script Tutorial里的例子是写一个 Follow的行为,拥有这个 Component GameObject会自动追踪 (面对着)一个目标对象

var target : Transform; 
  
function Update () { 
    transform.LookAt(target); 
}

        这个 Script暴露了一个 target变量 (应当作成员变量吧),使用者可以把其他对象的变 assign至这个变量。这 assignment有两种方法实现,其一是利用 Unity GUI 工具把一个 Component 实例的变量 (Transform) drag-and-drop至这个 Component实例的 target 变量,而另一个方法是写代码


var newTarget = GameObject.Find("Cube").transform; 
GetComponent(Follow).target = newTarget;

       用代码就可以这样动态改变这些 Component之间的联结方式。或者另一个说法是,GUI工具是可以设定起始的联结,而 Script可以在执行期改变这些联结。


渲染

       一个可被渲染的 GameObject需要有以几个 Components,以 Mesh为例:


1.  MeshFilter:用来找出现时的 Mesh对象


2. MeshRenderer:用来渲染 Mesh Component,会参考一个 Material对象


       要注要 Mesh Material 对象并非 Component,它们是继承自 Object的。你可以动态改变它们。但由于它们不是 Component,所以可以被分享,例如多个 GameObject MeshRenderer都参考到同一个 Material。一个 Component实例只属于一个 GameObject (所以在 UML中我用黑色钻石表示 Composition)。而 Light Camera 则是 Component,这意未着可以简单的设定联结。

分析

         Script对象模型是以 Component为基础的。透过把 Component实例加入 GameObject实例来组合不同功能的对象,而 Component实例之间可以建立联结。这种方式不需要透过继承 (inheritance),而是透过聚合 (aggregation)加入对象的功能和行为。使用聚合的好处是不会产生复杂的继承层阶,亦可以动态改变聚合的结构 (例如在执行期加入或移除 Component)。有一些细节我暂时未清楚,例如多个 Component在一个 GameObject中的执行次序如何设定;联结会否有 cylic的问题等等。可能要拿到软件再试用才可以知道。

结语

       的脚本系统给我的感觉是使用非常简单。透过很少的代码就能写一些行为,甚至把行为组合到对象中。但是,通常容易的东西都会有相对的缺点,例如在效能上或是 Scalability上。后者可能是一个很大的问题,当游戏规模扩大,Component和联结就会变成一个很复杂的 graph,由于连结是发生于执行期 (而非静态),可能要作改动会变得困难。换句话说,就是改几十个类别容易,改它们的几千个实例就会很困难。软件设计世界里当然没有银子弹,每个方案都适合不同的情况。我认为 Unity 的一个设计目标是容易使用,就是像 Virtools之流,可以给没有程式底子的人做游戏,相对来说做比较复杂的项目可能会遇到许多问题。但参考一下总可以给予对事物新的观点,或分析另一个科案的优越之处。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值