最近在利用U3D进行剧情动画的制作,要求是可以控制人物移动,播放动作,有对话,整个剧情动画都是由一个文本驱动的。因此具有较高的灵活性,而且也易于拓展,可以完全丢给策划去配置。
下面简单地介绍一下我的是如何实现的,主要是讲下思路,留给以后的自己看,当笔记记着,免得忘记
整个剧情系统的运作,有点类似状态机,是通过一个事件去触发另一个事件的发生,我把剧情动画中,所有可能出现的事件都列出来,发现,剧情动画只需要一下4种事件,就可以拼凑出一个简易的剧情动画
1.幕头事件:用于表示一段剧情的开始,这里面可以定义许多你想要在这一段剧情中,一些固定的数据,比如,这段剧情需要载入哪个场景,有哪些模型等
2.人物控制事件:用于定义一个人物的移动行为,怎么移动,移动到哪里,播放什么动画等
3.对白事件:用于定义一个对白事件,谁说话,说话的内容,说话时的动作等
4.镜头控制事件:用于控制镜头的行为,比如,播放镜头动画,或者是如何移动镜头
以上四种类型的事件,基本上可以拼凑出一个简单的剧情动画,举个例子:
镜头中只有人物B,突然有一个人物A,匆忙地跑到人物B面前,然后和B说,有人来敲门了。接着镜头从慢慢地朝向门的方向(就是看着门)。就这样一段小剧情,其实整个过程可以分割成这样
一。幕头定义(事件1):有人物A,人物B,房间的场景
二。人物移动(事件2):人物B从某一点,移动到另一点,同时播放跑步动作
三。对白事件(事件3):进行对白,B和A说,有人来敲门
四。镜头移动(事件4):让摄像机播放一个镜头移动的动画
然后通过剧情系统,让这四个事件按顺序执行,就像状态机一样,从一个状态转换到另一个状态,执行的顺序是:
先执行 事件1, 等事件1执行完毕后,触发事件2,然后事件2,等事件2执行完毕后,执行事件3,以此类推
因为当时在做的时候,就有利用一些状态机的特性,所以,我定义这四个事件的类的时候,是这样定义的
因此这四个事件都具有相同的方法,分别是
1.Begin():在这个事件开始前,进行的一些初始化动作
2.Update():这个事件所需要做的具体逻辑
3.Exit():在事件完成时,最后需要做的事情
学过状态机的人,应该都看得出,其实这就是一个状态基类的一些常规方法
至于这写函数里面的逻辑,暂时先不写了,要是有人需要,我再补上
最后,是剧情系统的类的定义,我这个也采用了一些状态机的一些方法。
剧情系统,主要是用来执行每个事件的Begin,Update,Exit等函数:
///
/// 初始化剧情动画U
///
private void Awake()
{
event.Begin(); // 开启某一个事件
}
void Update () {
if (m_allEnvent.Count <= 0) // 没有任何事件可以执行,表示整个剧情动画结束
{
ForceCloseStory(); // 结束整个剧情
return;
}
// 执行所有事件
for (int i = 0; i < m_allEnvent.Count; ++i) // m_allEnvent是所有正在发生的事件的一个事件列表
{
if (m_allEnvent[i].Update()) // 执行Update函数,如果返回TRUE则表示事件结束,需要进入Exit
{
m_allEnvent[i].Exit();
}
}
}
以上代码是我临时写的伪代码,只是为了表达一下,剧情系统的运作原理,具体的逻辑代码,可以参照有限状态机的实现,其实大体差不多。
最后来总结一下整个思路,首先是分割剧情动画中,包含哪些事件,然后进行提炼,封装成一个动画事件。然后通过触发的方式,去触发别的事件,触发的数量不一定是一个,你同时触发很多个事件。然后把这些动画事件类,都通过剧情系统来一一执行逻辑。
最后,是如何变成文本驱动,其实可以把所有的一些可变动数据,都当成一个成员变量,然后通过文本读取数据,对每个成员进行赋值。
比如,人物控制事件,它包含一个移动起始点,移动结束点,移动的速度,需要播放的动作名称,人物的Rota值等。
这些都可以通过自己定义读取方式,读取文本,然后赋值。