zoukankan      html  css  js  c++  java
  • 游戏性基础系统

    游戏性基础系统

      游戏性基础系统(gameplay foundation system):

        1)运行时游戏对象模型(runtime game object model)

        2)关卡管理及串流(level management and streaming)

        3)更新实时对象模型(real-time object model updating)

        4)消息及事件处理(messaging and event handling)

        5)脚本 (scripting)

        6)目标及游戏流程管理(objectives and game flow management)

      其中1)运行时对象模型是最复杂的,通常它需要提供以下功能:

        1)动态地产生(spawn)及消灭(destroy)游戏对象。

        2)联系底层引擎系统

        3)实时模拟对象行为

        4)定义新游戏对象类型

        5)唯一的对象标识符(unique object id)

        6)游戏对象查询(query):根据ID查找对象,或是根据任意条件做高级查找,如寻找玩家20m以内的所有敌人

        7)游戏对象引用(reference)

        8)有限状态机(finite state machine, FSM)

        9)网络复制(network replication)

        10)存档及载入游戏、对象持久性(object persistence)

    运行时对象模型架构

      游戏对象模型的2种架构:

        1)以对象为中心(object-centric):每个对象含一组属性及行为,这些都会封装在那些对象实例的类之中。游戏世界只不过是游戏对象的集合。容易产生单一庞大的类层次结构(monolithic class hierarchy)。一个类越是在类层次结构中越深的地方,就越难以理解、维护及修改。因为要理解一个类,就需要理解其所有父类。

        此方式最大的问题是,当设计层次选择了某个标准,就很难甚至不可能用另一个完全不同的标准分类。比如按物种分类的生物,要按颜色分类就不好办。mix-in类可以改善改方式。一个类可以派生自主要继承层次结构中的一个且仅一个类,但也可以继承任意数量的mix-in类(无基类的独立类)。通常更好的做法是合成(composition)或聚合(aggregation),而不是继承他们。

        把Window派生自Rectangle类。然而,一个视窗并不是一个长方形,它只拥有一具长方形,用于定义其边界。因此,这个设计问题的更好解决方法是把Rectangle的实例安置于Window类之中,或是令Window拥有一个Rectangle的指针或参考。面向对象设计中,“有一个”的关系称为合成(composition),合成的对象与主对象有同样的生命周期。对于主对象与子对象生命周期不同步的设计,称为聚合(aggregation)。

        要降低游戏类层次结构的宽度、深度、复杂度,一个十分有用的方法是把“是一个”关系改为“有一个”关系。业界成熟的方式是使用组件模式:

          1)“枢纽”HUB组件模式

          2)通用组件模式

          3)纯组件模式

        2)以属性中心(property-centric):每个游戏对象仅以唯一标识符表示。我们先定义游戏对象可能含有的属性集合,然后为每个属性建表。此设计更能有效地使用内存,因为我们只需存储实际上用到的属性。SoA(struct of array)的性能优于AoS(array of struct)

    世界组块的数据格式

    1、二进制对象映像,把每个对象的二进制映像(binary image)写入文件,对于指针和虚函数表需要特殊处理。

    2、序列化(serialization),XML解析之慢众所周知。

    3、生成器(spawner)是游戏对象的轻量、仅含数据的表示方式,可用于运行时实例化及初始化游戏对象。

    游戏世界的加载和串流

      游戏加载系统主要有2个功能:

        1)人磁盘加载游戏世界组件及其它用到的资产至内存中。

        2)管理这些资源的内存分配及释放。

      加载包括:

        1)简单的关卡加载,玩家需要等待关卡载入,期间会显示静态或简单动画的二维加载画面。

        2)串流加载,即预加载

        3)关卡加载区域,区域之间可能会有重叠,每个区域配有一个表,列出玩家位于该区域时内存应该包含的世界组块。

      内存管理采用池分配器,为每种类型对象生成一个池分配器,避免内存碎片。

      游戏存档分为:

        1)存储点存档,这法较为简单,因为可以避免对大量世界数据的记忆

        2)任何地方皆可存档

    对象引用与世界查询

      几个实现对象引用的方式:

        1)指针

        2)智能指针

        3)句柄。句柄会有引用过时对象的问题,解决此问题的方案之一是,在每个句柄中加入唯一的对象标识符。

      游戏对象查询可以提供几下以种能力:

        1)以唯一标识符搜寻游戏对象

        2)对合乎某条件的所有对象进行迭代

        3)搜寻射线路线以及范围内物体

    实时更新游戏对象

      “差一帧”问题引起的状态不一致是bug的主要来源。相比游戏对象模型,低阶引擎子系统才是性能关键。

    事件与消息泵

    1、为每种事件定义一个虚函数,如OnExplosion()。这种方式的坏处在于,所有的对象都必须实现OnExplosion,即使是不响应此函数的对象也要实现。

    2、把事件封装成event,基类event提供类型,子类event提供具体内容,通过统一的OnEvent(Event *evt)来传递。

      关于事件的类型,有2种方法:

      1)enum枚举,此法有以下几个缺点,首先,所有的类型聚合在一起,破坏封装。其二,类型硬编码,其三,硬编码被改变后,对于存储于磁盘上的内容无法修改。

      2)使用字符串,缺点是占用内存点,消耗大。

      关于事件的参数,有以下几种方法:

      1)统一的variant集合

      2)键值对,此法可以解决variant的次序问题。

      事件的参数必须深拷贝出去,采用池分配可以有效减少内存碎片。但是采用event模式,会加大调度困难,因为无法追溯事件的发送者。

    3、事件处理器,即OnEvent的实现可以用switch来实现。另外,在设计上可以采取职责链模式。

    4、使用事件注册机制可以减少需要响应事件在范围。

    5、即时消息发送可能会导致栈开销过大,层次过深。

    6、事件响应的逻辑可以通过世界编辑器开放给策划,由策划来完成。

    7、事件机制可以提供排队的功能,以及延时响应功能。

    脚本

      游戏脚本语言通常有2种:

      1)数据定义语言(data-definition language)

      2)运行时脚本语言(runtime scripting language)

      对于大多数工作室而言,更合适的方未能是选择一个知名且成熟的脚本语言。游戏引擎必须要能执行脚本代码,脚本代码也需要发志引擎中的操作。运行时脚本语言的虚拟机通常是嵌入游戏引擎中的。引擎启动虚拟机,需要时执行脚本代码,并管理脚本的执行情况。

      脚本需要和游戏对象互动,其中一个方法是在脚本中以不透明的数值类型句柄(handle)来引用对象。

  • 相关阅读:
    Sentinel实现熔断和限流
    Nacos 服务注册和配置中心
    SpringCloud Sleuth 分布式请求链路跟踪
    SpringCloud Stream消息驱动
    SpringCloud Bus消息总线
    SpringCloud Config分布式配置中心
    Geteway服务网关
    Hystrix断路器
    libecc:一个可移植的椭圆曲线密码学库
    第四十二个知识点:看看你的C代码为蒙哥马利乘法,你能确定它可能在哪里泄漏侧信道路吗?
  • 原文地址:https://www.cnblogs.com/tekkaman/p/3649018.html
Copyright © 2011-2022 走看看