前言
Unity3D插件是Unity3D平台为了使游戏代码能够调用原生代码而提供的一种方式,移动端SDK的Unity3D插件则是SDK开发团队为了Unity3D平台的用户能够正常使用SDK功能而开发的一类插件。
移动端SDK的Unity3D插件的开发、维护随着SDK的种类及SDK所包含的功能的发展、变化而变化,SDK开发团队在处理这些变化时,会面临到这些变化所带来的相关问题:
- 插件开发的相关成本问题
- 插件开发的效率问题
- 插件开发的质量、稳定性问题
这些问题造成的影响或者是由于SDK的种类的增加而增大、或者是由于SDK功能的更新、修改而变化、或者兼而有之,原因可能是由于不同SDK插件的开发的不规范、开发核心架构的不统一、相关插件开发流程、开发语言的不熟悉等。
Unity3D的插件模板化探索,是在明确这些问题原因的基础上,尝试解决这些问题。实现在Unity3D插件开发过程中,统一流程规范、统一核心架构、降低相关成本、提高开发效率等目标。
SDK Unity3D插件的架构
一、Unity3D插件的基础功能
Unity3D插件的基础功能即实现游戏代码调用原生代码的一般流程如下图所示:
开发者只需要使用基于C的语言(iOS端一般使用C语言)来定义函数、在函数中调用原生功能后将这些函数编译到库中,然后再创建一个C#脚本来调用库中的函数,即可实现对原生代码的调用。
二、Unity3D插件架构的设计、实现
Unity3D插件架构是在实现Unity3D插件基础功能的架构的基础上,根据移动端SDK的通用特性,设计实现的。
部分移动端SDK的通用特性如下所示:
- 支持不同设备的移动端SDK
- SDK功能调用时的自定义参数等
- SDK部分功能的异步回调等
Unity3D插件架构图:
该架构在实现Unity3D插件调用SDK功能的基础上,增加了插件功能的可扩展性,满足了大部分SDK Unity3D插件开发的需求。有效的解决了插件开发过程中遇到的参数传递、参数个性化、iOS端函数回调、增加不同类型设备的支等问题。Unity3D插件在统一架构的基础上进行开发,可有效降低开发过程中遇到的质量、稳定性问题等。
Unity3D插件模板的设计实现
插件架构的设计、实现只是解决了开发过程中的部分问题,无法针对开发流程、相关成本等问题提出有效的解决办法。插件模板可以理解为在统一开发规范流程中依据插件框架设计实现目标插件的开发流程,因此插件模板可以彻底的解决这些问题。
一、Unity3D插件架构的解析
因为插件模板是根据C#语法,将脚本详细信息按照架构设计的格式组织起来,所以我们需要在设计、实现插件模板时,通过对结果即插件脚本的具体内容进行逆操作的方式来获取脚本详细信息。
对结果的逆操作,即根据架构设计的格式,对插件脚本中的每一个组成部分进行解析操作,以获得组成元素,直至获得最小组成元素。
如下图所示为插件组成元素关系图:
通过对插件组成元素的解析操作,我们可以确认模板可操作的最小组成元素单位是: Property、Method及Enum,以此为基础的可用组成元素是: Class、Interface、Namespace等,进而得到组成元素的构成信息及不同元素间的相互关系信息。这些信息是插件模板信息流的组成元素。
二、Unity3D插件模板的流程设计
插件模板的一般定义插件模板是根据C#语法,将脚本详细信息按照架构设计的格式组织起来 粗略描述了插件模板的流程。
我们在插件模板所需信息已经确定的基础上,插件模板的详细流程如下图所示:
**注:**用户维护的描述信息是指按照一定的结构形式来描述基础组成元素与可用组成元素的构成信息和相对关系等。
插件模板在经过信息处理、语法转换、语法组合等的流程处理后,生成了目标的插件脚本,真正实现了插件开发统一规范、统一架构的目标。插件开发者不再需求学习新的开发语言、积累不同SDK开发、维护经验等,可以将更多的精力放在统一格式的描述信息的维护及原生SDK功能的开发维护上去。
三、Unity3D插件模板的代码实现
1、缓存元素信息储存、语法转换实现逻辑:
-
#以下三个类型统称为模板中的基础结构,用来描述模板中的最基础的信息
-
class CProperty
-
attr_accessor :info, :access, :type, :name, :value, :device, :delegate
-
private :info
-
#初始化方法
-
def initialize(detail_info)
-
…
-
end
-
#详细描述, public type property_name = default_value;
-
def description
-
return ‘public type property_name = default_value;’
-
end
-
end
-
class CMethod
-
attr_accessor :info, :access, :name, :cases, :device
-
private :info
-
#初始化方法
-
def initialize(detail_info)
-
…
-
end
-
#详细描述, void method_name(type param);
-
def description
-
return ‘void method_name(type param);’
-
or
26.return ‘void method_name(type param) {}’
27.end
28.end
30.class CEnum
31.attr_accessor :info, :name, :params, :ret, :desc, :device, :virtual, :delegate
-
private :info
-
#初始化方法
-
def initialize(detail_info)
-
…
-
end
-
#详细描述, enum name { type case_name = 0; }
-
def description
-
return ‘enum name { type case_name = 0; }’
-
end
-
end
-
#模板中CClass类是为了描述插件脚本中类的具体信息
-
#包括:类名、属性、方法、Enums等信息
-
#构成插件脚本中类的基本信息描述
-
class CClass
-
attr_accessor :info, :class_name, :interface, :properties, :enums, :methods
-
attr_accessor :enum_classes, :property_classes, :method_classes
-
private :info, :enums, :properties, :methods
-
#初始化方法
-
def initialize(detail_info)
-
…
-
end
-
def properties
-
end
-
def enums
-
end
-
def mehtods
-
end
-
end
-
#模板中CNamespace类是为了描述插件脚本中命名空间内的详细信息
-
#包括: 类、全局的属性、全局的变量等
-
#构成了插件脚本中命名空间的基本信息描述
-
class CNamespace
-
attr_accessor :info, :file_name, :file_path, :classes, :enums, :properties, :methods
-
attr_accessor :methods_classes, :properties_classes, :enums_classes, :detail_classes
-
private :info, :classes, :enums, :properties, :methods
-
def initialize(detail_info)
-
…
-
end
-
end
2、语法组合:
-
Unity3D脚本内容的一般格式:
-
using System;
-
namespace xx.xx.com {
-
public class name {
-
public void method_name() {}
-
…
-
}
-
}
-
语法组合即插件模板按照脚本的一般格式将组成元素语法组合起来,生成脚本详细内容
Unity3D插件模板的使用效果
插件模板实现了插件的开发流程从传统的架构设计、代码实现到唯一文件的开发、维护的转换。
插件模板开发模式与传统开发模式具体效果比较:
由此可知,插件模板化开发相对于传统开发,以牺牲一定的开发自由度为条件,将整个插件的框架设计、开发规范等统一实现,解决了传统开发中遇到的主要问题,具有很大的实践优势。
同时,因为插件的模板化开发还处于初级阶段,具体功能还不完善,还面临着许多的问题和挑战:
- 模板化开发自由度的提升,支持更多的描述信息转换
- 模板化开发有效性的检验,即对映射生成的代码进行合法、有效性检查
- 模板化开发语法、规范等的可扩展性,增加模板支持的插件类型等