游戏引擎架构2:How,Why?

  我们往往基于兴趣驱动去学习一样东西,而这种方式让我们更有兴趣去驾驭和达成手段。深入下去后我们便会清楚自己的手中的工具是怎样构成的,并想办法去拆解他。

  作为一名工程师,有好奇心去了解事物的机理构造是自然而然的事。

  面向对象方法中有许多宏观的问题值得思考。在做游戏引擎架构的时候尤为重要。

  我们建立了Object类,让他能渲染RenderObject类,让他有动画AnimObject,让他有物理PhysicsObject。如果就这样我们让这种方式单一继承。如果我们要实现一个生物角色,那是非常好的,这些属性我们都需要。

  如果我们仅仅是要一个不带AnimObject的KActor呢?很明显我们的类中将会出现冗余。

  虚幻引擎使用了Component的方式可以让你在自己的类中嵌入想要的属性类。

  这种实现方法是:主干类Object拥有所有组建的指针,构造函数中设其为Null,在析构函数中将其delete即可。

  游戏对象的载入,对于大部分的静态模型或者固定的碰撞体积,引擎在加载的时候直接读取其机器码。而对于动态的对象,会使用类如XML键值码来进行翻译。

  虚幻中也有Archetype等方式。

  

  载入和卸载是引擎的重要环节,引导机器将内容加载到内存,用完之后卸载掉他们。确保每个对象都是用正确的类去实例化,管理其生成和销毁。

  谈谈关卡加载:在进入游戏中时,加载所有游戏关卡都要使用的游戏资源,例如你的角色和HUD UI之类。我们将这些内容放置在堆栈中,这些内容将会至于堆栈的底部常驻留Load and stay resident LSR数据,以后的关卡都往里添栈即可。

  StreamLevel用到了一个PersistanceLevel和阻隔室,其他小关卡桥接的在这个主管卡中,使用IO异步让CPU可以用一个线程加载及卸载关卡。逻辑上可以用一些小谜题或是门让玩家避免等待,同时设置一些不能让玩家折返的场景,我最常用的便是跳下去或是机关阻碍。

  为对象分配内存是一个非常棘手的课题,因为内存碎片,下面介绍三种手法,这些方法都能避免内存浪费:

  1.一次加载完,仅仅是让敌人隐藏和出现而已。并不是严格意义的spawn和destroy。对关卡设计师的考验较大。

  2.分配相同大小的内存池,这会让所有对象占据一个等大小内存,要么会出现内存浪费,要么对象占用内存过大无法分配。

  3.按照指数来设置内存池,例如8k,16k,等等每次查找内存的大小找最小的开始。挪动指针会很快找到。但会造成碎片产生。解决碎片的方法是内存重定位,使空余内存偏移,但得小心出现恐怖的事情,动了不该动的内存。

  存档和加载世界有本质相同点,就是从磁盘上将信息加载到内存中。但不像加载游戏世界,仅仅是存储玩家能觉察到的假象即可,例如玩家的生成位置,当前携带和解锁的关卡及弹药。欺骗他们吧,其实Joel已经不是那个Joel了,他死了XD

  游戏是一个实时系统,引擎总是随着一定的频率来更新游戏中的对象,不管是他们的渲染,动画,碰撞还是物理声音等。每个对象可视为一个过程,之前的状态,决定当前的t-Δt.

  引擎会管理一个或多个时钟,其中一个是实时的,还有一些不是。例如不同对象这样我们可以设置快进快慢等。

  

原文地址:https://www.cnblogs.com/NEOCSL/p/3593792.html