数据驱动的游戏系统功能加载方法、设备及存储介质

文档序号:754052 发布日期:2021-04-06 浏览:33次 >En<

阅读说明:本技术 数据驱动的游戏系统功能加载方法、设备及存储介质 (Data-driven game system function loading method, device and storage medium ) 是由 李荣华 孙培文 池婧雯 于 2020-12-24 设计创作,主要内容包括:本申请实施例提供一种数据驱动的游戏系统功能加载方法、设备及存储介质。系统的源文件包含多个存放有行为单元的类,每个类具有类描述;在加载游戏的场景管理功能时,根据外部输入的数据(即配置数据)决定调用哪些类中的成员方法来创建场景管理单元,可基于外部数据确定游戏系统场景管理逻辑,实现了游戏系统的数据驱动。在系统的行为由外部输入的数据决定的前提下,可通过改变外部输入的数据来改变游戏系统的运行行为,实现新的系统功能,提升系统的易用性和可复用性。(The embodiment of the application provides a data-driven game system function loading method, equipment and a storage medium. The source file of the system comprises a plurality of classes which are stored with behavior units, and each class is provided with a class description; when the scene management function of the game is loaded, the member methods in which classes are called are determined according to the externally input data (namely configuration data) to create the scene management unit, the scene management logic of the game system can be determined based on the external data, and the data driving of the game system is realized. On the premise that the behavior of the system is determined by externally input data, the operation behavior of the game system can be changed by changing the externally input data, so that a new system function is realized, and the usability and reusability of the system are improved.)

数据驱动的游戏系统功能加载方法、设备及存储介质

技术领域

本申请涉及互联网技术领域,尤其涉及一种数据驱动的游戏系统功能加载方法、设备及存储介质。

背景技术

一个大型系统,需要组织和管理大量的数据,并需要对相应的数据采用对应的行为进行处理。通常,相似的数据或在一个行为中需要使用的数据,会被组织在一起。系统基于数据执行某一功能时,需要找到与数据对应的行为,并对数据执行这些行为。在大型的系统中,如何处理被共用的数据和行为,并为数据和行为创建合理的关联方式,是提升系统性能的关键环节。

在一种常用的现有技术中,将共用数据和行为分别抽取为单元,并基于单元组合的方式实现不同的系统功能。但是,这种方式中,被抽取的单元不直接面向系统功能,可读性和易用性较差。同时,行为单元和数据单元的耦合性较高,不利于提升系统的内聚性。因此,有待提出一种新的解决方案。

发明内容

本申请的多个方面提供一种数据驱动的游戏系统功能加载方法、设备及存储介质,用以提升系统的内聚性和系统代码的可复用性。

本申请实施例提供一种数据驱动的游戏系统场景管理功能加载方法,所述游戏系统的源文件包含:多个类,每个类具有类描述;所述多个类中,用于存放场景管理单元的类以及用于存放场景数据单元的类相互解耦;所述方法包括:获取所述游戏系统的配置数据,所述配置数据包含待加载的场景管理功能对应的场景管理单元的标识;基于反射机制,从已注册的类描述中,确定与所述场景管理单元的标识对应的第一目标类的类描述;根据所述第一目标类的类描述,从所述第一目标类中查询所述场景管理单元对应的成员方法;调用所述场景管理单元对应的成员方法,在所述游戏系统的内存中创建所述场景管理单元,以基于所述配置数据对所述游戏系统的场景管理功能进行驱动。

进一步可选地,所述场景管理单元包括:二叉树场景管理单元、四叉树场景管理单元或者八叉树场景管理单元。

进一步可选地,在调用所述场景管理单元对应的成员方法,在所述游戏系统的内存中创建所述场景管理单元之前,还包括:确定所述游戏系统所需的场景数据单元的标识;基于反射机制,根据所述场景数据单元的标识,确定所述场景数据单元所在的第二目标类的类描述;根据所述第二目标类的类描述,访问资源文件中的所述第二目标类,得所述场景数据单元;将所述场景数据单元加载到内存中供所述场景管理单元使用,以基于所述场景数据单元对所述游戏系统的场景管理功能进行驱动。

进一步可选地,所述方法还包括:响应编辑器的编辑操作,确定待编辑的场景数据单元的标识;根据所述待编辑的场景数据单元的标识,确定所述待编辑的场景数据单元所在的第三目标类的类描述;基于反射机制,根据所述第三目标类的类描述,从所述第三目标类中,确定与所述待编辑的场景数据单元对应的成员变量;根据所述成员变量,对所述编辑器的代码模板中的编辑对象赋值,得到所述待编辑的场景数据单元的编辑代码;运行所述待编辑的场景数据单元的编辑代码,生成所述待编辑的场景数据单元的编辑面板,以供用户对所述待编辑的场景数据单元进行编辑。

进一步可选地,基于反射机制,根据所述第三目标类的类描述,从所述第三目标类中,确定所述待编辑的场景数据单元对应的成员变量,包括:基于所述第三目标类的类描述,访问所述第三目标类中的成员变量;若访问到的成员变量的类型为基础数据类型,则将所述访问到的成员变量作为所述待编辑的场景数据单元对应的成员变量;若所述访问到的成员变量的类型为类描述的类型,则基于所述访问到的成员变量的类描述,对所述访问到的成员变量进行递归遍历,直至访问到基础数据类型的成员变量,作为所述待编辑的场景数据单元对应的成员变量。

进一步可选地,所述方法还包括:响应新增场景管理单元的操作,获取所述新增的场景管理单元所在的第四目标类的类描述;对所述第四目标类的类描述进行注册,以更新所述已注册的类描述,以供后续根据所述第四目标类的类描述,访问所述新增的场景管理单元。

进一步可选地,所述方法还包括:响应新增场景数据单元的操作,获取所述新增的场景数据单元所在的第五目标类的类描述;对所述第五目标类的类描述进行注册,以更新所述已注册的类描述,以供后续根据所述第五目标类的类描述,访问所述新增的场景数据单元。

进一步可选地,所述方法还包括:获取所述游戏系统的实时负载数据;展示所述实时负载数据,以供用户根据所述实时负载数据更新所述配置数据;获取更新的配置数据,并根据所述更新的配置数据,动态调整所述游戏系统中实时运行的场景管理单元。

进一步可选地,所述方法还包括:确定所述游戏系统包含的场景管理功能模块;根据所述场景管理功能模块包含的子场景管理功能,对所述场景管理功能模块进行拆分,得到所述多个子场景管理功能各自对应的场景管理单元。

本申请实施例提供的游戏系统功能加载系统中,系统的源文件包含多个存放有行为单元的类,每个类具有类描述;在加载游戏的场景管理功能时,根据外部输入的数据(即配置数据)决定调用哪些类中的成员方法来创建场景管理单元,可基于外部数据确定游戏系统场景管理逻辑,实现了游戏系统的数据驱动。在系统的行为由外部输入的数据决定的前提下,可通过改变外部输入的数据来改变游戏系统的运行行为,实现新的系统功能,提升系统的易用性和可复用性。

附图说明

此处所说明的附图用来提供对本申请的进一步理解,构成本申请的一部分,本申请的示意性实施例及其说明用于解释本申请,并不构成对本申请的不当限定。在附图中:

图1为本申请一示例性实施例提供的系统功能加载方法的流程示意图;

图2为本申请一示例性实施例提供的运行时创建子系统的流程示意图;

图3为本申请一示例性实施例提供的游戏系统功能加载方法的流程示意图;

图4为本申请一示例性实施例提供的电子设备的结构示意图。

具体实施方式

为使本申请的目的、技术方案和优点更加清楚,下面将结合本申请具体实施例及相应的附图对本申请技术方案进行清楚、完整地描述。显然,所描述的实施例仅是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本申请保护的范围。

一个具有特定功能的系统,需要组织和管理大量的数据,并对相应的数据采用对应的行为进行处理。通常,相似的数据或在一个行为中需要使用的数据,会被组织在一起。系统通过一些解决方案找到与这些数据对应的行为,并对数据执行这些行为,来完成一个系统功能的执行。

在构建系统时,通常需要关注以下几点,以提升系统性能:

其一,如何处理被共用的数据和行为。一个系统的需要提供众多不同的功能,部分不同的功能需要一些共同的数据和行为。因此,在设计系统时,若多种功能可以共享部分数据和行为,则可避免在每一个行为中重复实现相同的数据结构。

其二,数据和行为的关联方式。每一个行为需要特定的数据,而在执行某一个行为时,如何找到所需要的数据,决定了行为与数据的耦合程度。若行为与数据的耦合过高,则会导致行为和数据的复用性变差,进而,在对相似的数据结构实现相似的行为时,容易因为微小的区别而大量地新增代码。

其三,如何描述数据和行为来实现功能。数据结构和行为,一般通过具体的代码硬编码实现。若需要实现不同功能,则需要直接修改代码,以修改数据结构或者行为逻辑,进而导致系统的扩展成本和维护成本较高。

针对上述技术问题,在本申请一些实施例中,提供了一种解决方案,该解决方案一方面解耦了系统功能的运行逻辑与行为和数据之间的关系,另一方面,采用“数据驱动”的思想,使得系统的功能由外部输入的数据来驱动,提升系统的内聚性。以下结合附图,详细说明本申请各实施例提供的技术方案。在申请实施例中,可预先根据系统的功能,将系统的功能拆分成多个行为单元(或称为组件)和多个数据单元,即将需要共用的行为和数据抽取为单元实现共用。

其中,数据单元,包含一组逻辑和使用上强相关的数据。例如,数据单元可包括:位置数据单元、颜色数据单元、距离数据单元、角度数据单元、场景数据单元等等。

其中,行为单元,包含可对数据执行特定操作的功能函数。一个行为单位可用于单独执行一种行为。例如,行为单元可包括:移动(move)单元、剔除(culling)单元、渲染(render)单元、数据管理(manage)单元等等。

本实施例中的系统,可实现为游戏系统、物流仓储系统、商超管理系统等等,本实施例包含但不限于此。当需要将系统实现为某种具有特定功能的系统时,可根据系统的业务逻辑,将系统的功能拆分为合适的行为单元和数据单元。

以系统实现为游戏系统为例,在游戏场景中,可将游戏系统中的物体(实体)的功能分解为众多行为单元和行为所需的数据单元,将这些单元进行组合,即可得到最终的游戏系统中的实体。

其中,行为单元和数据单元的组合可以是多样的,基于多种行为单元和数据单元进行任意自由组合,可得到具有不同功能的游戏实体。例如,对于游戏系统中的物体,都需要位置数据,以及更新位置数据的行为。此时,可提取出位置数据单元,以及移动位置的行为单元,以供所有实体共用。

其中,行为单元和数据单元可分别封装在类中,且行为单元和数据单元位于不同的类中,以实现行为单元和数据单元之间解耦。即,系统源文件包含的多个类中,用于存放行为单元的类以及用于存放数据单元的类相互解耦,以降低数据单元和行为单元之间的依赖关系。针对行为单元而言,行为单元采取的行为,具体可取决于与行为单元组合的数据单元包含的数据内容。

继续以游戏系统为例,在游戏场景中,游戏实体中可存放数据单元的类的指针或索引,通过指针或者索引可以获取数据单元。一组数据单元的指针或者索引可组成一个游戏实体。当游戏实体的数据单元与不同的行为单元进行组合时,可实现游戏实体的不同功能。例如,当游戏实体的颜色数据单元与渲染单元组合时,渲染单元可实现游戏实体的颜色渲染功能;当游戏实体的颜色数据单元与发光单元组合时,发光单元可实现使游戏实体发射具有颜色的光线的功能;当游戏实体的颜色数据单元与绘图单元组合时,绘图单元可实现使游戏实体绘制特定颜色的图像的功能,不再一一赘述。

在本实施例中,提供了一种基于“反射(reflection)机制”对数据单元和行为单元进行访问的方法。在反射机制中,对每一个封装有数据单元和行为单元的类,生成对应的类描述,在系统运行时,可通过类描述对类进行访问、检测或者修改。其中,该类描述包括类具有的成员变量、成员函数、静态变量、静态函数、对齐方式、内存大小、类名称、继承关系等等信息。

在一些实施例中,基于本实施例提供的方法获取到的类描述,可包含类的类型(Type)、类的成员列表members:List<ClassDataMember>、类中的成员方法列表methods:List<ClassMethod>、类名称name:const char*等等。

在基于类描述对类中的数据进行访问时,可采用预先编写的的访问函数,将被访问的类的类描述作为函数中的变量,进而实现对类中的数据进行访问。在一些实施例中,根据类描述对类进行访问的函数,可包括:

根据类描述中的数据成员的描述名称,查找类中的数据成员的函数:findMember(const char*name):constClassDataMember*。

根据类描述中的成员方法的描述名称,查找类中的成员方法的函数:findMethod(const char*name):constClassDataMethod*。

检测继承关系的函数:IsTypeOf(const ClassDescriptor*cd):bool。

检测是否含有某个成员变量的函数:hasMember(const char*name):bool。

检测是否含有某个成员方法的函数:hasMethod(const char*name):bool。

获取类描述的名称的函数:getName():const char*。

上述函数仅用于示例性说明,本申请实施例提供的用于实现反射的函数包含但不限于上述函数。上述函数可作为代码模板,在开发人员进行编码时,可复用上述函数,实现对任意数据结构的类进行访问。

可选地,为实现上述反射机制,可预先注册系统中的每个类的类描述(ClassDescriptor),并可对已注册的类的标识以及类描述的对应关系进行组织,生成可供查询的索引信息。进而,当访问某一个类时,可提供类的标识,并基于该类的标识,在索引信息中进行查询,得到类的类描述。

其中,类的标识,可以是类的名称,该名称可以采用字符串进行表示。例如,针对待查询的类M,可以通过TypeDispenser.GetClassDescriptor(“M”)来获得类M的类描述。其中,上述反射机制可基于C++(一种编程语言)编写程序实现,或者,可基于其他类型的编程语言实现,本实施例不做限制。

基于上述,本申请实施例提供一种数据驱动的游戏系统功能加载方法,图1为数据驱动的游戏系统功能加载方法的流程示意图,如图1所示,该方法包括:

步骤101、获取系统的配置数据,所述配置数据包含待加载的功能对应的行为单元的标识。

步骤102、基于反射机制,从已注册的类描述中,确定与所述行为单元的标识对应的第一目标类的类描述。

步骤103、根据所述第一目标类的类描述,从所述第一目标类中查询所述行为单元对应的成员方法。

步骤104、调用所述行为单元对应的成员方法,在所述系统的内存中创建所述行为单元,以基于所述配置数据对所述系统的功能进行驱动。

其中,配置数据,可配置对系统的功能需求。通常,该配置数据可写在配置文件中。用户或系统功能开发人员在确定系统的运行逻辑之后,可在配置文件中,写入实现系统的某一个或者多个功能所需的一个或者多个行为单元的标识。其中,行为单元的标识,可以是行为单元的名称,或者行为单元编号等等,本实施例不做限制。

如图2所示,配置文件输入系统后,可由反射模块根据配置文件执行反射操作。在反射操作中,可根据行为单元的标识和类的对应关系,确定待加载功能对应的行为单元所在的目标类,并从已注册的类描述中,确定该目标类的类描述。为便于描述和区分,将该行为单元所在的目标类,描述为第一目标类。

在确定第一目标类的类描述后,可根据第一目标类的类描述,唯一地确定第一目标类,并从第一目标类中查询该行为单元对应的成员方法。在查询到行为单元对应的成员方法后,可调用执行该成员方法,以在系统的内存中创建该行为单元。其中,一个行为单元又可称为一个子系统,如图2所示。基于类描述和反射机制创建一个或者多个子系统后,可由系统管理器对该一个或者多个子系统进行管理,此处不赘述。

以下将结合一些具体的例子进行说明。

假设,存在类A,该类A含有成员变量member1,member2和member3,以及成员方法method1,method2。若不使用基于类描述的反射机制,那么,给定类A的实例a,在调用方法method1时,需要如下调用:

a.method1();

这种调用方式,依赖于实例a在编译期的结构,并且需要明确知道类A是否具有方法method1,需要在编译期进行检查。

若使用实施例提供的基于类描述的反射机制,则可以如下调用:

Method*method1=classDescriptorOfA.findMethod(“method1”);

If(method1!=nullptr){invoke();}

其中,classDescriptorOfA,表示类A对应的类描述;

classDescriptorOfA.findMethod(“method1”),表示根据类A对应的类描述,从类A中查找指定成员方法“method1。

这种调用方式,不依赖于编译期的任何结构,只依赖于在运行时进行方法的查找和调用。在调用时,不需要知道这个类是否具有这个方法,也不需要在编译期进行检查。

例如,一个函数具有输入参数obj,当调用这个输入的类的moveTo()方法时,若不使用基于类描述的反射机制,则应当知道传入的类的类型,比如是A&obj,或者B&obj,然后再调用obj.moveTo()。

若使用基于类描述的反射机制,则只需要一个void*obj的输入参数,以及一个类描述(ClassDescriptor),就可以进行方法的调用,而不需要知道这个参数在编译期的类型。

例如,通过类描述对类进行检测时,可使用类描述来检测类之间的关系。比如,可通过classDescriptorA.IsTypeOf(other)来检测类A的继承关系,或者classDescriptorA.HasDataMember(name)来检测类A中是否含有某个具有指定名称(name)的类。

例如,通过类描述对该类进行修改时,首先可基于类描述找到类中的成员变量的类描述,接下来基于修改函数以及成员变量的类描述,对成员变量进行修改。

比如,可使用classDescriptor.FindMember(name)获得成员变量的描述dataMemberDescriptor,然后通过dataMemberDescriptor.data(void*object)或者dataMemberDescriptor.set(void*object,void*value)等接口,实现对数据成员的修改。

又例如,某一个类包含一个成员变量position,类型为vector、一个成员变量color,类型为Color。在输出这个类的信息时,可基于反射机制,调用display(object,classDescriptor)进行输出,如下代码所示:

其中,displayPOD(),可针对所有基础数据类型进行处理,进而,该输出函数可对任意的类中的数据进行展示。若不使用基于类描述的反射机制,那么,若要对所有的类都能做到信息的输出,则需要编写与类的数量匹配的重载方法,十分耗费工作量。

在本实施例中,系统的源文件包含多个存放有行为单元的类,每个类具有类描述;在加载功能时,根据外部输入的数据(即配置数据)决定调用哪些类中的成员方法来创建行为单元,可基于外部数据确定系统运行逻辑,实现了系统的数据驱动。在系统的行为由外部输入的数据决定的前提下,可通过改变外部输入的数据来改变系统的运行行为,实现新的系统功能,提升系统的易用性和可复用性。

在一些可选的实施例中,上述系统实现为游戏系统时,游戏引擎需要对游戏场景中的大量对象进行组织和管理。通过良好的组织,引擎可以快速的完成对象的索引、遍历、筛选等操作。为了达成这一目标,引擎会使用一些特定的数据结构,例如二叉树、四叉树、八叉树。对于不同的场景,需要使用不同的数据结构区管理。

在现有的技术方案中,配置数据结构时,每种数据结构对应一个枚举值,需要基于枚举值确定数据结构,并且通过一个函数来产生指定的数据结构。例如:

在上述过程中,一方面对于配置文件中的存储的int类型强行转化可能存在风险(溢出),错误值不容易查错。另一方面,添加新的类型需要改写GenerateSceneGraph中的switch-case代码块。当系统中类似的逻辑较多时,修改工作量巨大。

若采用本实施例提供的基于类描述的反射机制,则可基于以下的方法对游戏的场景数据进行管理,如图3所示,包括:

步骤301、获取所述游戏系统的配置数据,所述配置数据包含待加载的场景管理功能对应的场景管理单元的标识。

步骤302、基于反射机制,从已注册的类描述中,确定与所述场景管理单元的标识对应的第一目标类的类描述。

步骤303、根据所述第一目标类的类描述,从所述第一目标类中查询所述场景管理单元对应的成员方法。

步骤304、调用所述场景管理单元对应的成员方法,在所述游戏系统的内存中创建所述场景管理单元,以基于所述配置数据对所述游戏系统的场景管理功能进行驱动。

其中,该场景管理单元包括:二叉树场景管理单元、四叉树场景管理单元或者八叉树场景管理单元。选择何种场景管理单元执行游戏系统的场景管理功能时,可通过配置文件进行需要加载的场景管理单元。以下将结合代码进行示例性说明。

可选地,基于反射机制,确定包含场景管理单元的类的操作,可以由ClassDescriptor实现。其中,ClassDescriptor可以通过TypeDispenser(),直接使用类的标识对应的字符串进行查询。

在游戏场景中,基于具有管理功能的行为单元(即场景管理单元),对场景数据进行管理的操作,可通过配置文件进行配置,如下所示:

基于上述代码,可以直接由配置文件(SettingFile)产生对应的SceneGraph(组织场景图数据的行为单元)来管理场景,而不需要额外的将配置文件的内容转化为枚举值内容。通过修改配置文件,就可以直接的影响系统将要生成的场景管理数据结构。

同时,相对于现有技术,在增加新的场景管理方式时,不需要改写代码中可能存在多处的switch-case或者if-else代码段,使用现有的代码即可完成处理。基于该优势,可在游戏系统中存在多人协作,不需要编辑大量的代码即可同时增加大量配置项。

除了配置数据管理方式之外,游戏中的各个模块的配置均可采用上述基于配置文件的驱动方式。游戏中的配置项的具体配置方式,可写在配置文件中,在新增配置项或者减少配置项时,不需要修改任何读写、创建的代码逻辑,提升了游戏系统的易用性和可复用性。

在一些示例性的实施例中,基于行为单元对应的成员方法,在系统的内存中创建行为单元之前,可将行为单元所需的数据单元加载到内存中。

可选地,可根据系统的声明信息,确定系统所需的数据单元的标识。其中,系统的声明信息,可通过宏定义的方式写在系统的代码文件中。读取并解析代码文件中的宏定义,即可确定系统所需的数据单元的标识。

获取到数据单元的标识后,可基于反射机制,根据数据单元的标识,确定数据单元所在的目标类的类描述。在一些是实施例中,根据数据单元的标识,确定数据单元所在的第二目标类的类描述的操作,可基于getClassDescriptor(name)函数实现。在本实施例中,将数据单元所在的目标类,描述为第二目标类。接下来,可基于反射机制,根据第二目标类的类描述,访问资源文件中的第二目标类,得数据单元,并将数据单元加载到内存中,以供行为单元使用。

其中,系统实现为游戏系统时,该数据单元可实现为游戏的场景数据单元,该场景数据单元可被场景管理单元使用,实现游戏场景的数据管理功能。

其中,根据第二目标类的类描述,访问第二目标类中的数据单元,并将数据单元加载到内存中的操作,可基于预先编辑的代码模板实现,该代码模板包含基于类描述对类进行访问的函数(如前述实施例的列举的函数),用于实现针对某一变量的访问逻辑以及加载逻辑。其中,代码模板中的该变量的值可由外部传入。在从第二目标类中确定数据单元后,可将该数据单元对应的成员变量传入该代码模板,即,根据该数据单元对应的成员变量对代码模板中的变量进行赋值,得到用于访问并加载该数据单元的代码,进而,实现对数据单元的访问以及加载。

基于上述,在内存中创建行为单元之后,行为单元可遍历内存中具有特定类型的数据单元的实体,并根据遍历到的数据单元包含的数据,执行对应的功能。例如,将移动单元(Move单元)加载至内存后,移动单元可通过反射机制遍历系统中所有Position(位置)类型的数据单元,并根据Position(位置)类型的数据单元包含的位置数据,更新Position(位置)类型的数据单元对应的实体的位置。

在这种加载数据单元的方法中,采用了基于类描述的反射机制,使得代码模板具有极高的复用率,无需考虑数据单元所在的类的类型,能够完成针对任意类型的类中的数据单元的的访问操作。

在本申请实施例中,整个系统的行为由外部输入数据(即配置数据)决定的一种表现为:系统中的每一个行为单元的执行情况,由数据单元的属性决定。行为单元基于类的类描述,查找到数据单元后,可通过数据单元的类型,来判断行为单元是否执行,以及如何执行。

例如,对于移动单元(Move单元),在执行移动操作时,可通过反射机制快速判断某个Object(对象)是否具有一个Position(位置)类型的数据单元。若有,则Move单元可根据数据单元中的位置数据,对该对象执行移动操作;否则,Move单元不执行移动操作。

又例如,对于发光单元,在执行发光操作时,可通过反射机制,快速判断某个Object(对象)具有的光源数据单元的属性。该光源的数据单元的属性可包括:光源类型(点光源、线光源)、照射距离、颜色、照射角度等等。若该光源数据单元的属性为:红色的点光源,则发光单元可执行红色点光源的发光操作,以使得该对象呈现发出红色点光源的效果。若该光源数据单元的属性为:水平照射的绿色的线光源,则发光单元可对该对象执行绿色线光源的水平发光操作,以使得该对象呈现发出绿色水平照射的线光源的效果。

在本申请实施例中,整个系统的行为由外部输入数据(即配置文件)决定的另一种表现为:系统中有多少个行为单元在执行,由外部输入数据决定。

基于反射机制,可以在运行时创建和管理所有的行为单元。通过将所需的行为单元的列表存储到外部配置文件,即可以通过该配置文件在创建程序实例时,动态创建所需的行为单元,进而决定整个程序实例的起始状态。

进一步的,通过在配置文件中增加控制行为单元的参数,例如行为单元所需的缓存空间的大小、行为单元的线程数等等,可以控制整个程序的运行。

基于上述,可进一步通过修改配置文件,在系统的运行期对实时运行的行为单元进行动态修改。即,根据“基于类描述的反射机制”,动态调整系统的负载均衡。以下将进行示例性说明。

可选地,系统或者运行有系统的设备,可获取系统的实时负载数据,并展示该实时负载数据,以供用户根据实时负载数据更新系统的配置文件;待用户更新配置文件之后,系统可根据更新后的配置文件,加载或者卸载指定的行为单元,以动态调整所述系统中实时运行的行为单元。进而,实现了运行时的系统负载实时调整方法,有利于系统健康运行。

进一步地,基于类描述和反射机制,还可实现一种不依赖数据结构的运行时数据编辑方法,以下将进行示例性说明。

可选地,响应编辑器的编辑操作,可确定待编辑的数据单元的标识;其中,该待编辑的数据单元的标识,可由编辑用户提供。接下来,根据待编辑的数据单元的标识,确定待编辑的数据单元所在的目标类的类描述。以下为便于区分,将待编辑的数据单元所在的类描述为第三目标类。

接下来,可基于反射机制,根据第三目标类的类描述,访问资源文件中的第三目标类,从第三目标类中,得到待编辑的数据单元对应的成员变量。接下来,根据该待编辑的数据单元对应的成员变量,对编辑器的代码模板中的编辑对象进行赋值,得到待编辑的数据单元的编辑代码。运行该待编辑的数据单元的编辑代码,即可生成该待编辑的数据单元的编辑面板,以供用户对该待编辑的数据单元进行编辑。

在这种方式中,存在编辑数据单元的需求时,无需关注数据单元的结构,只需获取数据单元所在的类的类描述,即可基于反射机制获取到数据单元。一方面,这种为数据单元生成编辑面板的代码框架可复用于多种不同结构的数据单元,降低开发成本;另一方面,当数据单元的结构变化时,不会对访问数据单元的方式造成影响,提升访问效率。

在本实施例中,可将所有的数据单元,以JSON(JavaScript Object Notation,JS对象简谱)格式存储在系统的资源文件中。资源文件中,包含每个对象的类描述(ClassDescriptor)名称,以及类中各个成员变量的值。其中,类中的成员变量的值可以嵌套,即成员变量本身也可以是一个对应ClassDescriptor的类型。

因此,基于第三目标类的类描述,访问第三目标类中的成员变量时,可进一步判断成员变量的类型;若该访问到的成员变量的类型为基础数据类型,则将可将该访问到的成员变量作为待编辑的数据单元对应的成员变量,并直接生成该成员变量的编辑面板。

若该访问到的成员变量的类型为类描述的类型,则可基于该访问到的成员变量的类描述,对该访问到的成员变量进行递归遍历,直至访问到基础数据类型的成员变量,作为待编辑的数据单元对应的成员变量,并为该基础类型的成员生成该变量的编辑面板。

其中,基础类型指的是语言工具自带的数据类型,包括:byte、short、int、long、float、double、char、boolean、指针类型、unsigned int,unsigned short等等。

也就是说,从JSON格式存储的资源文件中读取对象后,可以通过ClassDescriptor遍历该对象。在遍历的过程中,对每种基础数据类型的成员变量,可使用对应的编辑面板;对非基础数据类型的成员变量,则可以递归进行这一过程,直到所有的值都是基础数据类型。若成员变量为非基础类型,则可认为成员变量嵌套有其他的类,此时可基于ClassDescriptor进行递归查找,直到查找到的所有成员变量的值均为基础类型。

在这种方式中,当类中的成员变量的值存在嵌套时,可利用反射机制,对基础数据类型的成员变量创建对应的编辑面板,并基于递归的方法,实现对非基础数据结构的成员变量的编辑,避免了对每一个类重复写编辑面板。

为数据单元生成编辑面板的过程大致包括:从资源文件中读取数据单元、序列化保存数据单元至文件以及生成编辑界面等步骤。上述过程可用伪代码表示为:

基于上述算法,可以递归地处理所有非基础数据类型的变量,且上述过程只依赖于运行时的数据。进而,不论是序列化、反序列化、编辑器,都只需要一套基础的代码即可面对绝大多数的数据结构的改变。

以下将结合游戏场景,对采用基于类描述的反射机制的数据编辑方法进行示例性说明。

其中,编辑器的代码模板可以为:

在上述代码模板中,classType的值,可从游戏系统的配置文件中读取,该值可用于表示待访问的目标类的标识。基于上述编辑器的代码模板,传入任何类,利用反射系统的ClassDescriptor,都可以通过递归调用Process()将该类分解到ProcessBaseType()的粒度上。

针对每一个包含数据单元的类,即使该类中的成员变量发生变化,也无需修改编辑器的代码。对类中的成员变量进行添加、删除、修改的操作,可由反射操作直接映射处理到ClassDescriptor中,不需要对Process()进行任何修改。同样,新增任何类型,都可以直接调用Process()函数进行处理,无需新增任何代码即可完成对该类型的编辑功能,极大减少了游戏编辑器的工作量,以及后期维护编辑器的工作量。

进一步的,上述数据的编辑操作并不直接依赖于游戏引擎的源代码。编辑器代码只依赖于ClassDescriptor,只需要开放ClassDecriptor头文件和相关数据,编辑器即可工作。编辑器与引擎脱离后,编辑器只需要关注游戏数据的编辑,而不需要关心引擎的逻辑,因此可使得数据驱动更流畅。

在本申请的上述各实施例的基础上,若存在新增行为单元以及数据单元的需求时,无需重新编写新增代码,只需为新增的行为单元或者数据单元生成类描述,并且对类描述进行注册。以下将进行示例性说明。

可选地,响应新增行为单元的操作,可获取新增的行为单元的第四目标类的类描述;接下来,对第四目标类的类描述进行注册,以更新源文件中已注册的类描述。当后续访问新增的行为单元时,可从已注册的类描述中获取第四目标类的类描述,并基于该第四类的类描述,访问新增的行为单元。其中,当系统实现为游戏系统时,上述新增的行为单元,可包括场景管理单元。

可选地,响应新增数据单元的操作,可获取新增的数据单元所在的第五目标类的类描述;接下来,可对第五目标类的类描述进行注册,以更新源文件中已注册的类描述。当后续访问新增的数据单元时,可从已注册的类描述中获取第五目标类的类描述,并基于该第五类的类描述,访问新增的数据单元。其中,当系统实现为游戏系统时,上述新增的数据单元可包括场景数据单元。基于上述实施方式,当新增行为单元或者数据单元时,无需进行复杂的代码编辑即可实现新增,极大提升了开发效率、降低了开发成本。

在一些可选的实施例中,可通过对系统进行细粒度拆分,使得系统模块之间摆脱逻辑上的依赖。可选地,在对系统进行细粒度拆分是,可确定该系统包含的功能模块;接下来,根据该功能模块包含的子功能,对该功能模块进行拆分,得到多个子功能各自对应的行为单元。

例如,以游戏系统中的裁剪(culling)功能模块为例,裁剪分为多个不同的裁剪方式,例如四叉树裁剪、八叉树裁剪,视锥裁剪等等。可根据上述每种裁剪方式,创建行为单元,每个行为单元可以单独作为一个子系统(subsystem)。在系统运行时,可基于配置数据,配置裁剪功能模块包含上述多个行为单元中的一个或者多个行为单元。

基于这种实施方式,针对系统中的每个非核心的功能模块而言,可将该功能模块的每个实现方式,均封装为一个行为单元,进而,形成行为单元(子系统)->功能模块->系统模块,这样的三层结构。

除非核心模块之外,可选地,针对系统的核心模块而言,系统运行时,核心模块具体包含的功能模块,也可由配置文件进行配置,进而实现以“数据(配置文件)”系统的运行模式。

以游戏系统为例,游戏核心系统模块(core module),可能包含资产管理、线程管理、渲染等多个功能模块。上述核心系统模块具体包含哪些功能模块,可以由配置文件配置。在一些其他实施例中,还可根据需求在配置文件中配置数学模块(math module),场景模块(scene module),对象池模块(object model module),编辑器模块(editor module)等功能模块。

上述功能模块之间的耦合度较低,因此面向不同的功能需求时,可以根据需求组合不同的功能模块来实现功能需求。例如,在编辑器场景或者测试场景中,通过配置文件,在核心模块中加入编辑器模块或者调试模块,以实现编辑功能或者调试功能。

上述基于配置文件组合并管理功能模块和行为单元的方式,实现了基于外部数据对系统进行驱动,避免了对系统本身的代码进行修改,降低了系统的开发成本和维护成本。除此之外,系统拆分得到的各个子系统具备较高的独立性,系统之间的互相依赖只体现在数据流上,而不存在与系统代码本身。除了必须的基础系统,可以根据运行的负载来动态的启动和停止一些子系统,具有较高的灵活性。

需要说明的是,上述实施例所提供方法的各步骤的执行主体均可以是同一设备,或者,该方法也由不同设备作为执行主体。比如,步骤301至步骤304的执行主体可以为设备A;又比如,步骤301和302的执行主体可以为设备A,步骤303的执行主体可以为设备B;等等。

另外,在上述实施例及附图中的描述的一些流程中,包含了按照特定顺序出现的多个操作,但是应该清楚了解,这些操作可以不按照其在本文中出现的顺序来执行或并行执行,操作的序号如301、302等,仅仅是用于区分开各个不同的操作,序号本身不代表任何的执行顺序。另外,这些流程可以包括更多或更少的操作,并且这些操作可以按顺序执行或并行执行。需要说明的是,本文中的“第一”、“第二”等描述,是用于区分不同的消息、设备、模块等,不代表先后顺序,也不限定“第一”和“第二”是不同的类型。

图4是本申请一示例性实施例提供的电子设备的结构示意图,如图4所示,该电子设备包括:存储器401以及处理器402。

存储器401,用于存储计算机程序,并可被配置为存储其它各种数据以支持在电子设备上的操作。这些数据的示例包括用于在电子设备上操作的任何应用程序或方法的指令,联系人数据,电话簿数据,消息,图片,视频等。

其中,存储器401可以由任何类型的易失性或非易失性存储设备或者它们的组合实现,如静态随机存取存储器(SRAM),电可擦除可编程只读存储器(EEPROM),可擦除可编程只读存储器(EPROM),可编程只读存储器(PROM),只读存储器(ROM),磁存储器,快闪存储器,磁盘或光盘。

其中,图4所示的电子设备,用于执行一种数据驱动的游戏系统功能加载方法,该系统的源文件包括多个类,每个类具有类描述;所述多个类中,用于存放行为单元的类以及用于存放数据单元的类相互解耦。

在执行上述系统功能加载方法时,处理器402,与存储器401耦合,用于执行存储器401中的计算机程序,以用于:获取系统的配置数据,所述配置数据包含待加载的功能对应的行为单元的标识;基于反射机制,从已注册的类描述中,确定与所述行为单元的标识对应的第一目标类的类描述;根据所述第一目标类的类描述,从所述第一目标类中查询所述行为单元对应的成员方法;调用所述行为单元对应的成员方法,在所述系统的内存中创建所述行为单元,以执行所述功能。

进一步可选地,处理器402在调用所述行为单元对应的成员方法,在所述系统的内存中创建所述行为单元之前,还用于:根据所述系统的声明信息,确定所述系统所需的数据单元的标识;基于反射机制,根据所述数据单元的标识,确定所述数据单元所在的第二目标类的类描述;根据所述第二目标类的类描述,访问资源文件中的所述第二目标类,得所述数据单元;将所述数据单元加载到内存中供所述行为单元使用,以基于所述数据单元对所述系统的功能进行驱动。

进一步可选地,处理器402还用于:响应编辑器的编辑操作,确定待编辑的数据单元的标识;根据所述待编辑的数据单元的标识,确定所述待编辑的数据单元所在的第三目标类的类描述;基于反射机制,根据所述第三目标类的类描述,从所述第三目标类中,确定与所述待编辑的数据单元对应的成员变量;根据所述成员变量,对所述编辑器的代码模板中的编辑对象赋值,得到所述待编辑的数据单元的编辑代码;运行所述待编辑的数据单元的编辑代码,生成所述待编辑的数据单元的编辑面板,以供用户对所述待编辑的数据单元进行编辑。

进一步可选地,处理器402在基于反射机制,根据所述第三目标类的类描述,从所述第三目标类中,确定所述待编辑的数据单元对应的成员变量时,具体用于:基于所述第三目标类的类描述,访问所述第三目标类中的成员变量;若访问到的成员变量的类型为基础数据类型,则将所述访问到的成员变量作为所述待编辑的数据单元对应的成员变量;若所述访问到的成员变量的类型为类描述的类型,则基于所述访问到的成员变量的类描述,对所述访问到的成员变量进行递归遍历,直至访问到基础数据类型的成员变量,作为所述待编辑的数据单元对应的成员变量。

进一步可选地,处理器402还用于:响应新增行为单元的操作,获取所述新增的行为单元所在的第四目标类的类描述;对所述第四目标类的类描述进行注册,以更新所述已注册的类描述,以供后续根据所述第四目标类的类描述,访问所述新增的行为单元。

进一步可选地,处理器402还用于:响应新增数据单元的操作,获取所述新增的数据单元所在的第五目标类的类描述;对所述第五目标类的类描述进行注册,以更新所述已注册的类描述,以供后续根据所述第五目标类的类描述,访问所述新增的数据单元。

进一步可选地,处理器402还用于:获取所述系统的实时负载数据;展示所述实时负载数据,以供用户根据所述实时负载数据更新所述配置数据;获取更新的配置数据,并根据所述更新的配置数据,动态调整所述系统中实时运行的行为单元。

进一步可选地,处理器402还用于:确定所述系统包含的功能模块;根据所述功能模块包含的子功能,对所述功能模块进行拆分,得到所述多个子功能各自对应的行为单元。

需要说明的是,图4示意的电子设备应用于游戏场景时,本实施例中的系统可实现为游戏系统,行为单元可实现为游戏系统中的场景管理单元,该场景管理单元可包括:二叉树场景管理单元、四叉树场景管理单元或者八叉树场景管理单元。其中,数据单元,可实现为游戏系统中的场景数据单元,不再赘述。

进一步,如图4所示,该电子设备还包括:显示组件403、通信组件404、电源组件405、音频组件406等其它组件。图4中仅示意性给出部分组件,并不意味着电子设备只包括图4所示组件。

其中,通信组件403被配置为便于通信组件所在设备和其他设备之间有线或无线方式的通信。通信组件所在设备可以接入基于通信标准的无线网络,如WiFi,2G、3G、4G或5G,或它们的组合。在一个示例性实施例中,通信组件经由广播信道接收来自外部广播管理系统的广播信号或广播相关信息。在一个示例性实施例中,通信组件可基于近场通信(NFC)技术、射频识别(RFID)技术、红外数据协会(IrDA)技术、超宽带(UWB)技术、蓝牙(BT)技术和其他技术来实现。

其中,显示器404包括屏幕,其屏幕可以包括液晶显示器(LCD)和触摸面板(TP)。如果屏幕包括触摸面板,屏幕可以被实现为触摸屏,以接收来自用户的输入信号。触摸面板包括一个或多个触摸传感器以感测触摸、滑动和触摸面板上的手势。所述触摸传感器可以不仅感测触摸或滑动动作的边界,而且还检测与所述触摸或滑动操作相关的持续时间和压力。

其中,电源组件405,为电源组件所在设备的各种组件提供电力。电源组件可以包括电源管理系统,一个或多个电源,及其他与为电源组件所在设备生成、管理和分配电力相关联的组件。

本实施例中,系统的源文件包含多个存放有行为单元的类,每个类具有类描述;在加载功能时,根据外部输入的数据(即配置数据)决定调用哪些类中的成员方法来创建行为单元,可基于外部数据确定系统运行逻辑,实现了系统的数据驱动。在系统的行为由外部输入的数据决定的前提下,可通过改变外部输入的数据来改变系统的运行行为,实现新的系统功能,提升系统的易用性和可复用性。除此之外,在一些实施例中,可通过修改配置数据,实现系统的动态负载均衡。配合反射以及数据驱动的方法,可以在系统启动后,再根据负载情况,修改配置数据,动态地启动和停止一些行为单元或者模块,从而均衡系统的负载。

相应地,本申请实施例还提供一种存储有计算机程序的计算机可读存储介质,计算机程序被执行时能够实现上述方法实施例中可由电子设备执行的各步骤。

本领域内的技术人员应明白,本发明的实施例可提供为方法、系统、或计算机程序产品。因此,本发明可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本发明可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。

本发明是参照根据本发明实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。

这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。

这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。

在一个典型的配置中,计算设备包括一个或多个处理器(CPU)、输入/输出接口、网络接口和内存。

内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器(RAM)和/或非易失性内存等形式,如只读存储器(ROM)或闪存(flash RAM)。内存是计算机可读介质的示例。

计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他内存技术、只读光盘只读存储器(CD-ROM)、数字多功能光盘(DVD)或其他光学存储、磁盒式磁带,磁盘存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括暂存电脑可读媒体(transitory media),如调制的数据信号和载波。

还需要说明的是,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、商品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、商品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、商品或者设备中还存在另外的相同要素。

以上所述仅为本申请的实施例而已,并不用于限制本申请。对于本领域技术人员来说,本申请可以有各种更改和变化。凡在本申请的精神和原理之内所作的任何修改、等同替换、改进等,均应包含在本申请的权利要求范围之内。

24页详细技术资料下载
上一篇:一种医用注射器针头装配设备
下一篇:虚拟对象的显示方法、装置、终端及存储介质

网友询问留言

已有0条留言

还没有人留言评论。精彩留言会获得点赞!

精彩留言,会给你点赞!

技术分类