《游戏引擎架构》读书笔记(三)

来源:互联网 发布:ui切图软件 编辑:程序博客网 时间:2024/05/18 01:49

一.动画系统

(1)动画系统的演变:

a)传统的帧动画:2D游戏中,将动作逐帧播放。好吧,我只停留在这个水平。

b)动画纹理:与帧动画差不多,使用面向摄像机的四边形,贴上一连串的纹理。虽然很挫,但是现在仍有应用,特别远距离的物体还是可以使用这种动画方式的。

c)刚性阶层式动画:将角色拆分为各个部分,可以按照关节运动,但是由于是刚性运动,三角形不会有所拉伸,因而会有“裂缝”,看起来不是很真实。

d)每顶点动画:蛮力方法,为每个顶点添加随时间改变的动作信息,虽然三角形会有变化,但是由于存储量太大,不常用。

e)变形目标动画:与上面的方法大致相同,都是存储顶点信息,但是存储量较少,用于极端情况,运行时将两种或以上的姿势混合,就可以生成动画。通常用于面部动画。

f)蒙皮动画:最常用的动画系统。兼具刚性阶层动画和顶点动画的优点。由刚性的骨头和外部圆滑的三角形网格皮肤构成,顶点会追踪关节,当关节移动时,蒙皮可以自然的拉伸。

关于动画数据,一定要进行压缩,不然会过于庞大。

(2)动画系统,由于GPU和CPU的负载,不可能像电影那样锁定帧率,所以游戏的帧率是不稳定的,因而动画系统必须要能够调节时间比例,可以根据帧数采样,帧数不仅限于整数,可能是小数,甚至可以根据是负数来形成倒转的动画。

(3)局部时钟和全局时钟:动画自身有一个局部的时间线,而角色有全局时间线。最简单的就是直接使用动画的局部时间线来控制动画,但是有可能会出现多个角色动画不同步的问题。使用全局时间线,协调不同角色之间的动画。

(4)选择性载入动画,由于动画较大,一次性载入肯定不现实。一般采取的方法是初始化时载入一组核心的动画集,比如角色移动的动画。其余的按需求载入。有的引擎把动画打包成逻辑组,以此单位载入及卸载。

(5)动画系统的架构:

         a)动画管道:用于产生动画,设置动画播放参数等等,并根据骨骼,动画片段等等数据,计算产生动画。这里产生的动画貌似是一些原子动画,可以组合。

         b)动作状态机:置于动画管道之上,通常为有限状态机,通过状态来控制播放哪个动画。如果有同时播放几个动画的情况,可以通过状态层使用多个独立的状态机来控制。每个状态对应一个或者几个动画管道产生的原子动画,将其混合。关于这个状态,最好使用脚本来控制,因为动画的编辑,一定要尽快看得到状态,所以也有很多引擎提供了可视化的动画编辑器。当然,除了要根据状态显示不同的动画之外,还要注意不同状态之间的过渡,

         c)动画控制器:相当于控制动画状态机的一层,实现更高层的动画控制,具体负责一个动作的动画。

 二.碰撞检测系统(collisiondetection system)及刚体动力学(rigid body dnamic)

(1)一些常用的物理SDK如Bullet和PhysX,Havok等。以后打算去看一看PhysX

(2)碰撞检测系统:判断世界中的物体是否有接触,每个逻辑对象用一个或者多个几何形状代表,通常用简单的几何体来代表。检测在某些时刻是否有相交,其实碰撞检测系统就是一个几何体相交检测器。

(3)碰撞物理世界:collision world,碰撞引擎通常通过一个碰撞世界的数据结构管理所有的可碰撞实体。相比将碰撞信息存储于游戏对象本身,将碰撞数据统一管理,可以免去管理多余数据结构,并且有效封装,从可理解性,可维护性,可重用性来说都有好处。

(4)碰撞原型:

a)球体(最高效)

b)胶囊体(比圆柱体和长方体高效)

c)传说中的AABB,(axis-alignedbounding box)中文叫轴对齐包围盒。6个面都与坐标系的轴平行,可以很方便的由两个点定义,一个是盒子在主轴上的最小坐标,另一个是最大坐标。优点在于可以很高速的测试和另一个AABB相交与否。但是要求比较高,AABB最好是保持与轴对齐,一旦物体旋转,其逼近形状很差,不能很好的适应物体。

d)OBB(orientedbounding box)定向包围盒。使用半长,半宽,半高,以及一个变换用来定位盒子的中心位置和方向。比较常用。

还有一些,不过对我来说简直太高大上了,还是先看看基础的吧。

对于复杂的物体,可以先进行整体的包围盒检测,如果检测成功了,再使用更高级的检测方法来检测,或者检测子部分。如果不成功,后面的步骤就可以直接省略。这样大大的提高了效率。

(5)关于碰撞检测,有一大堆高大上的算法。表示数学不好,基本看不懂。不过有一个地方还是要注意一下,关于移动物体的碰撞检测,可能会出现“隧穿”现象。正常我们做碰撞检测采用的是碰撞世界“快照”的方式,即每隔一段时间,查看有没有碰撞。但是就有可能出现类似子弹穿纸的情况,在时间间隔内,已经走过了范围,然而的确是碰到了。解决的办法是使用扫掠形状,比如从上一个位置到下一个位置形成一个胶囊体。检测这个胶囊体和另一个物体的碰撞即可。或者还有一种使用连续碰撞检测的方法,求得最早的冲击时间。

(6)碰撞检测的性能优化:碰撞检测是很耗费cpu的操作。所以一定要进行相关的优化。先进行空间的划分,八竿子打不着的就不检测了。然后进行中间阶段的检测,最后再进行精确检测。

(7)碰撞查询:其实有时候我们做碰撞检测不是要检测真正的物体和物体之间的碰撞,有时候是假想的物体。比如获得在给定范围内所有玩家对象。这样的操作成为碰撞查询。

         a)光线投射:ray  cast。貌似就是射线检测,光线投射通过起点p0和方向d,根据方程p(t) =p0 + td t属于【0,1】,t值即碰撞早晚的参数,因为碰撞检测会返回一组结果,通常为t值,击中的碰撞体,接触点的法矢量。

         b)形状投射:这个貌似很有用。比光线投射更加精准,而且能传回多个触点。经常用于判断摄像机是否与游戏世界中的物体碰撞。胶囊体投射常用于角色移动。

(8)碰撞回调:可以在碰撞检测中设置回调函数,用回调函数决定怎样处理碰撞。

(9)碰撞材质:这个想法好天才。类似图像的材质一样,将碰撞系统也设置一种材质,不同的材质有不同的碰撞效果,如音效,粒子,物理属性等。

(10)保证摄像机不要穿过物体,不然会穿帮。不过这并不是一件容易的事。通常使用包围球包围摄像机,在碰撞到物体之前,调整摄像机的位置或定向。

(11)物理系统必须定期更新,通常每帧更新一次,有时候可以使用上一帧的碰撞状态,或者接受一帧的延迟。可以单线程,也可以使用基于命令队列的多线程更新。

0 0
原创粉丝点击