UE3中Kismet概念及应用
Kismet是一个可视化脚本设计系统,允许用户快速简便地创设复杂的脚本序列,要想了解UE3中Kismet概念和应用,通过下文中的介绍你就知道了。
简要概述:
首先介绍Kismet的基本概念、它在引擎中所处的位置,然后通过几个简单的应用例子来引出Kismet有哪些基本序列类型、序列的代码架构层次以及UC脚本和Kismet的交互方式,最后,展示并解析UE3自带例子"DayAnd Night"的Kismet应用。
一,Kismet的基本概念:
Kismet:英文解释为:定数、天命。放到游戏开发里,大概意思就是能够左右游戏角色命运的东西吧。
Unreal里,简而言之,Kismet就是一个可视化的脚本编辑工具。如图下所示,它是由各种类型的可视化结点之间的连线组成,
因为Kismet的改动能够实时的在编辑器中展现,甚至能够断点调试,以视图连线的方式编辑游戏逻辑直观易懂,所以,它很适合用于快速设计及验证游戏性,它主要面向于关卡设计师。
说到可视化脚本编辑,除了Kismet,UE3编辑器中其他许多地方也有应用。例如,声音编辑器,如图所示:
动画树编辑器:
材质编辑器:
声音、动画、材质,Kismet这些都属于游戏资源,具化到UnrealEditor中分别为:SoundCue、AnimTree、Material、Map。它们都有一些共同特点:资源内部带有一些特定逻辑,如果用代码来编写或者用脚本来编辑会相当繁琐且不够直观,代码人员本身就有大量开发工作,不适宜牵扯到这种资源性编辑工作中,而美术人员对脚本代码又不够熟悉,所以,将这种资源性逻辑放到编辑器中进行可视化编辑是很有必要的。
上述每种资源编辑视图,都有固定的几大类结点,它们的逻辑就是由这些结点通过连线视图组成的。例如,AnimTree中的结点基类大概分为:动画节点、Morph结点、骨骼控制器结点,它们都共同继承自AnimObject类,该类在编辑器中表示一个可绘制的结点元素。再往下,可以根据游戏开发需要分别对上述基类的结点进行扩展。这几大类结点中,会有一类结点可以作为容器包含其他类型的结点,也就是说,AnimTree下的结点之间是一种组合模式的关系,类似于UI系统中的窗口层次接口。如图所示:
再比如,Material中包含了两大类结点MaterialExpression(材质表达式)和MaterialFunction(材质函数), 所有材质的特效都来自于这两类结点的连线视图,最终Unreal会将该连线视图自动转化为对应的Shader代码。同理,上述其他的资源内的结点组成都有类似的结构层次。只不过,材质、动画、声音编辑器的共同点都是,所有结点都是从左向右依次输出,将逻辑数据最终输出到一个最终的结点,这个结点存储了最终的逻辑数据,比如一个声音源、一个动画融合后的骨骼变化数据或者一个材质特效数据。而KISMET和它们不一样,KISMET每个结点是一个序列,所有序列都是通过事件依次触发,它的输出各种各样,没有特定的形态,也许是改变一个变量,也许是执行一段CG动画,也许是打开一盏灯,等等。
二,Kismet模块在引擎中的位置
我们先扯远点。游戏开发中,游戏引擎应该算是最经常听到的名词之一,但是游戏引擎这个词经常被过度泛称或者误用,其实游戏引擎架构,从低阶到高阶,大致分为以下三个层次:
1,第一层:图形API
它负责提供图形程序同图形硬件之间联系,将硬件层的功能抽象化,提供一组标准化的接口供图形程序员使用。目前图形API中,大家熟悉的OPEN GL和DIRECTX便是业界两大标准,游戏引擎基本脱离不了这两类API的使用。
2,第二层:图形引擎
图形引擎负责提供游戏逻辑程序同图形API之间的联系,它将图形API包装成与具体API无关的统一接口,逻辑程序不需要关心图形API到底是使用DIRECTX还是OPEN GL,能够用统一的代码在不同平台上进行开发。另外图形引擎更为重要的工作在于提供图形程序的基本模块:场景管理、资源管理、光照处理、后期特效等等。目前比较知名的图形引擎有:OGRE、Gamebryo、Renderware等,之所以叫它们做图形引擎,主要原因是这些引擎主要精力集中于对图形的处理,其他和游戏相关的模块涉及不多。
3,第三层:游戏引擎
同图形引擎不一样,游戏引擎除了提供图形引擎功能外,可能还包含音效引擎、物理引擎甚至网络引擎等。相比图形引擎,它提供了各种类型的资源编辑工具,如:地形编辑器、动画编辑器、材质、粒子编辑器、KISMET等。统一对象管理,例如内存管理、对象序列化、网络传输等等。另外它还提供了游戏开发的一般架构方案,为游戏开发者提供尽可能的功能性与便利性。例如:Unreal、Unity3D都属于这一阶层。
Kismet便是Unreal引擎提供给游戏开发者的一种便利性工具之一。它属于游戏引擎中的第三阶层。
当然,不同的游戏引擎和不同的图形引擎,都会有不同程度的差别,比如同样是图形引擎, OGRE和Gamebryo就有不同的Rough程度。同样是游戏引擎,Unreal和Unity3D也有不同的应用需求,从而构成引擎的各需求层次的市场。
三,几个简单的Kismet例子
为了引入Kismet中的各种类型的序列对象,我们先来看看几个简单的Kismet应用例子。
三,Kismet序列对象
Kismet视图逻辑中的每一个元素都被称之为一个序列对象,所谓序列,是有先后顺序关系的,Kismet中的每个结点都是一个序列,即它们都是按照时间先后顺序触发的。通过以上例子,我们可以总结出Kismet中的几大基本序列类型:
1,事件:鼠标键盘的输入事件、某游戏对象或者关卡发生的某些特定事件(比如对象间触碰、关卡加载)都属于事件,它是游戏逻辑的“发起者”,即KISMET序列触发的入口源头。
2,动作:当被激发时会执行特定动作。例如开关灯、粒子激活、打开声音、播放动画、生成Actor、设置某个变量值等。
3,变量:游戏中的对象或者基本类型数据如:Int、Float、Bool等。
4,条件:对变量进行条件判断的一些逻辑分支。
5,Matinee:它是一个动画CG工具,提供了对象或者变量随时间变化数值进行相应插值变化的工具,一般通过它制作过场动画或者动态的游戏性(如天气变化)。
整个架构层次如图:
四,脚本中操作Kismet序列的方式
前面讲过,Kismet属于游戏资源,它是保存在关卡资源中的即.umap文件中,无论是否编辑过关卡中的Kismet,每个关卡都会保存一个默认的根序列容器,通过如下方式获取:
LocalSequence DefaultSeq;
DefaultSeq= WorldInfo.GetGameSequence();
于是我们如果需要在UC脚本中对Kismet中特定的某个序列对象进行访问,都可以通过这个根序列查找到:
DefaultSeq.FindSeqObjectByName();
如果我们需要添加自定义的序列结点,也可以通过继承SequenceObject或者它的子类中某个序列类型来达到特定需求。
例如和操作变量相关的表达式,我们可以继承自:
SeqAct_SetSequenceVariable;
比如要相加两个变量,我们可以添加如下序列类:
class SeqAct_AddFloat extends SeqAct_SetSequenceVariable
native(Sequence);
cpptext
{
void Activated()
{
FloatResult = ValueA + ValueB;
OutputLinks(0).bHasImpulse = TRUE;
//Round the float result into the integer result
IntResult = appRound( FloatResult );
}
};
var() float ValueA;
var() float ValueB;
var float FloatResult;
var int IntResult;
defaultproperties
{
ObjName="AddFloat"
ObjCategory="Math"
InputLinks(0)=(LinkDesc="In")
OutputLinks(0)=(LinkDesc="Out")
VariableLinks(0)=(ExpectedType=class'SeqVar_Float',LinkDesc="A",PropertyName=ValueA)
VariableLinks(1)=(ExpectedType=class'SeqVar_Float',LinkDesc="B",PropertyName=ValueB)
VariableLinks(2)=(ExpectedType=class'SeqVar_Float',LinkDesc="FloatResult",bWriteable=true,PropertyName=FloatResult)
VariableLinks(3)=(ExpectedType=class'SeqVar_Int',LinkDesc="IntResult",bWriteable=true,PropertyName=IntResult)
}