一种用于Unity的热更新方法、装置、计算设备及计算机可读存储介质与流程

文档序号:29086483发布日期:2022-03-02 01:31阅读:279来源:国知局
一种用于Unity的热更新方法、装置、计算设备及计算机可读存储介质与流程
一种用于unity的热更新方法、装置、计算设备及计算机可读存储介质
技术领域
1.本技术涉及计算机技术领域,特别涉及一种用于unity的热更新方法、装置、计算设备和计算机可读存储介质。


背景技术:

2.在移动互联网领域,通常使用热更新的方式来实现app的功能更新或bug修复,用户打开app时即可实现更新,不用重新下载整个app,从而实现了良好的用户体验。现有技术中通常使用lua和ilruntime来实现热更新的功能,但是这两种方式都有各种的缺陷,例如基于unity引擎开发的应用多使用c#开发,如同时使用c#和lua两种语言会降低开发的效率,ilruntime虽然基于c#实现,但是目前使用限制较多,性能较差。


技术实现要素:

3.有鉴于此,本技术例提供了一种用于unity的热更新方法、装置、计算设备和计算机可读存储介质,以解决现有技术中存在的技术缺陷。
4.根据本技术实施例的第一方面,提供了一种用于unity的热更新方法,包括:为il2cpp工具添加il解释器;动态加载热更新程序集到il2cpp运行时中;将热更新程序集methodinfo结构中的methodpointer指向所述il解释器的 execute函数;对程序集函数执行指令进行拦截,将热更新程序集函数的执行任务交给解释器执行。
5.根据本技术实施例的第二方面,提供了一种用于unity的热更新装置,包括:aot编译器;il2cpp运行时环境;il解释器,用于对热更新的程序集代码进行解释执行;动态加载模块,用于动态加载热更新程序集到il2cpp运行时中;重定向模块,用于将热更新程序集methodinfo结构中的methodpointer指向所述il解释器的 execute 函数;拦截模块,用于对程序集函数执行指令进行拦截,将热更新程序集函数的执行任务交给解释器执行。
6.根据本技术实施例的第三方面,提供了一种计算设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机指令,所述处理器执行所述指令时实现所述热更新方法的步骤。
7.根据本技术实施例的第四方面,提供了一种计算机可读存储介质,其存储有计算机指令,该指令被处理器执行时实现热更新方法的步骤。
8.现有技术虽然通过lua或ilruntime能够解决部分热更新的需求,但是都存在开发效率、成本以及稳定性上的缺陷。通过本技术提供的热更新方法和装置,为unity的il2cpp工具添加了c++实现的解释器,对于无需更新的代码使用aot静态编译并本地执行;对于热更新程序集中的代码,则通过il解释器进行解释执行。由于没有引入其他的运行时,克服了现有技术中由于运行时的不同带来的兼容性问题。
9.进一步,基于对il2cpp运行时的理解,通过加载程序集时,对程序集中元数据字段的index进行编码,对不同的程序集元数据的获取进行了区分,实现了热更新的准备。在该方式中,由于是将热更新程序集和主程序加载到同一运行时中,不存在现有技术中ilruntime与il2cpp运行时的区分,消除了类型系统不兼容问题,让热更新的代码与主程序代码在同一运行时中无缝运行,也大幅提升了内存和运行效率。
10.热更新指令的执行通过函数来实现。在本技术实施例中通过对程序集加载过程的拦截,将来自热更新程序集函数的methodpointer指向解释器的execute函数;进而将包含了字节码信息的methodinfo结构体通过参数传递给解释器的excute函数,从而完成了热更新程序集中函数的解释执行。进而实现了函数的调用统一,保证了aot的c++函数和解释器函数之间运行的无缝性。
11.通过本技术实施例中的方法和装置,解决了游戏行业中基于unity开发的应用长期以来存在的热更新问题,提升了整个行业的开发效率、降低了开发成本。
附图说明
12.图1是本技术实施例提供的计算设备的结构框图;图2是本技术实施例提供的改进后的il2cpp架构的一示意图;图3是本技术实施例提供的用于unity的热更新方法的一示意图;图4是本技术实施例提供的用于unity的热更新装置的结构示意图。
具体实施方式
13.在下面的描述中阐述了很多具体细节以便于充分理解本技术。但是本技术能够以很多不同于在此描述的其它方式来实施,本领域技术人员可以在不违背本技术内涵的情况下做类似推广,因此本技术不受下面公开的具体实施的限制。
14.在本技术一个或多个实施例中使用的术语是仅仅出于描述特定实施例的目的,而非旨在限制本技术一个或多个实施例。在本技术一个或多个实施例和所附权利要求书中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其他含义。还应当理解,本技术一个或多个实施例中使用的术语“和/或”是指并包含一个或多个相关联的列出项目的任何或所有可能组合。
15.应当理解,尽管在本技术一个或多个实施例中可能采用术语第一、第二等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本技术一个或多个实施例范围的情况下,第一也可以被称为第二,类似地,第二也可以被称为第一。取决于语境,如在此所使用的词语“如果”可以被解释成为“响应于确定”。
16.在本技术中,提供了一种用于unity的热更新方法及装置、计算设备和计算机可读
存储介质,在下面的实施例中逐一进行详细说明。
17.图1示出了根据本技术一实施例的计算设备100的结构框图。该计算设备100的部件包括但不限于存储器110和处理器120。处理器120与存储器110通过总线130相连接,数据库150用于保存数据。
18.计算设备100还包括接入设备140,接入设备140使得计算设备100能够经由一个或多个网络160通信。这些网络的示例包括公用交换电话网(pstn)、局域网(lan)、广域网(wan)、个域网(pan)或诸如因特网的通信网络的组合。接入设备140可以包括有线或无线的任何类型的网络接口(例如,网络接口卡(nic))中的一个或多个,诸如ieee802.11无线局域网(wlan)无线接口、全球微波互联接入(wi-max)接口、以太网接口、通用串行总线(usb)接口、蜂窝网络接口、蓝牙接口、近场通信(nfc)接口,等等。
19.在本技术的一个实施例中,计算设备100的上述部件以及图1中未示出的其他部件也可以彼此相连接,例如通过总线。应当理解,图1所示的计算设备结构框图仅仅是出于示例的目的,而不是对本技术范围的限制。本领域技术人员可以根据需要,增添或替换其他部件。
20.计算设备100可以是任何类型的静止或移动计算设备,包括移动计算机或移动计算设备(例如,平板计算机、个人数字助理、膝上型计算机、笔记本计算机、上网本等)、移动电话(例如,智能手机)、可佩戴的计算设备(例如,智能手表、智能眼镜等)或其他类型的移动设备,或者诸如台式计算机或pc的静止计算设备。计算设备100还可以是移动式或静止式的服务器。
21.现有技术中,通常采用基于lua的各种框架如xlua或基于c#的运行时ilruntime来实现app的热更新。
22.基于lua的方案虽然能够实现热更新,但是也存在多个缺陷,例如:在c#项目中,如果使用lua来实现热更新逻辑,需要团队成员需要同时对lua和c#都特别熟悉,提高了开发的成本。
23.由于运行期间需要在c#和lua之间频繁切换,且lua调用c#的代码速度较慢,因此会降低游戏运行效率;无法使用集成开发调试环境,代码的单步调试,性能分析都缺乏良好的工具支持,难以满足大型工程的要求。
24.由于以上缺陷,现有技术中还提出了一种基于c#实现的ilruntime工具,用来实现同一种语言下的热更新方案。ilruntime为基于c#的平台如unity,提供了一个纯c#实现,快速、方便且可靠的il运行时,使得在不支持jit的硬件环境(如ios)能够实现代码的热更新。其实现原理是,ilruntime借助第三方mono.cecil库来读取热更新dll的pe信息,以及其中类型的所有信息,最终得到il汇编码,然后通过解释器解释dll中的il指令,逐条翻译并执行。该方式将不同类型的开发语言编写的热更新代码编译成il字节码,通过建立的il汇编器编译到dll文件中,当客户端加载该dll文件时,执行il字节码,然后初始化ilruntime,加载热更新代码。
25.虽然ilruntime克服了lua在热更新场景下的部分缺陷,但是它自身也存在着不少缺陷,首先由于它使用了外置解释器,热更脚本使用的类型系统与clr的类型系统并不统一,造成大量的不兼容问题,需要进行诸多额外的操作如跨域继承,辅助反射等,开发效率
很低;其次,在使用高级的语言特性组合时,如反射、泛型时,容易出现错误,稳定性较差;纯计算的性能弱于lua,计算密集型的代码不适合使用。
26.因此,在现有技术中,对于使用c#平台,如unity开发的应用,没有一种方便、高效、且成本低的热更新解决方案。
27.在本技术实施例中,为了解决上述问题,提出了一种用于unity平台的热更新方法和装置、计算设备和计算机可读存储介质。
28.在unity开发平台中,il2cpp 是一种新的脚本后处理(scripting backend)方式,针对平台编译输出的il(中间语言)进行处理,将il语言转换为静态的c++代码,然后再由各个平台的c++编译器直接编译成能执行的原生汇编代码,从而实现unity的跨平台开发。这种方式除了执行效率快以外,还可以利用各个平台的c++编译器对代码执行编译期优化,这样可以进一步减小最终游戏的尺寸并提高游戏运行速度,因此,几乎所有基于unity的开发过程都使用了il2cpp工具。
29.其中,il2cpp主要由两部分组成:aot(ahead of time)静态编译编译器(il2cpp.exe);运行时库(libil2cpp);aot编译器将il转换为c++代码,再交给各平台的c++编译器进行编译,由于使用的是aot静态编译,因此在编译时就必须完全确定需要用到的类型;运行时库则会提供诸如垃圾回收、线程/文件获取、内部调用直接修改托管数据结构的原生代的服务与抽象。
30.因此,在现有技术中,基于unity开发的项目采用的热更新方式几乎是il2cpp+lua或il2cpp+ilruntime之一,都无法避免其自身存在的缺陷。
31.无论是lua还是ilruntime,都采用了解释器的原理来对热更新的代码进行解释执行,不生成本地机器码,从而实现了各个平台上的热更新。因此在本技术的实施例中,通过对il2cpp工具进行自定义改造以及为il2cpp工具增加自定义解释器,从而实现了一种新的热更新架构,从根本上解决了现有技术存在的多种问题,极大的提高了unity的跨平台开发效率。
32.说明书附图1中的处理器120可以执行图2所示的用于unity平台的热更新方法中的步骤。图2中示出了实现用于unity平台的热更新方法的流程图,包括步骤202至步骤208。
33.步骤202:为il2cpp工具添加il解释器。
34.在该步骤中,通过为il2cpp工具添加il解释器,使得该工具具备了aot编译器、运行时环境和il解释器功能,具有了多个不同平台的编译和热更新基础。其中,对于无需更新的代码使用aot静态编译成c++代码,进而被目标平台编译为本地可执行程序;对于热更新程序集中的代码,则通过il解释器进行解释执行。
35.在现有的ilruntime工具中,使用c#完成了一个解释器,通过opcode来逐语句执行机器码,效率较低。在本技术实施例中,使用c++语言重新实现了一个高效的的解释器,引入常见的编译器优化技术,包括但不限于指令集转换,指令优化等,提升了内存和运行性能。
36.在本技术实施例中,从对il2cpp的clr运行时环境改造出发,将纯aot的运行时变成aot+解释器运行时,从根本上解决了热更新的问题,同时还保证了运行时的无缝性,克服了现有技术中由于运行时的不同带来的兼容性问题。
37.步骤204:动态加载热更新程序集到il2cpp运行时中;
il2cpp中的编译工具采用的是aot编译,即静态编译或运行前编译,这种编译方式需要在编译时访问所有的程序集并完成编译,并不支持动态加载其他的程序集。但是为了实现热更新,又必须动态加载热更新代码中的程序集到运行时中。因此,在本实施例中,对il2cpp运行时的元数据管理模块进行了改造,使之能够动态加载热更新的程序集动态库。
38.在一种具体的实施方式中,通过system.reflection.assembly.load方法加载热更新的程序集到运行时的程序集列表中。其中,与基于unity引擎开发的主应用一样,热更新的工程同样使用c#实现。
39.在原始的il2cpp运行时中,所有的程序集元数据信息,包括类名、属性名、字符串等信息都记录在global-metadata文件中,但该文件只包含了编译时包括的静态元数据信息,在进行查询元数据时仅直接访问一个只读的全局列表获得。因此在该状态下,即使动态加载了热更新程序集到运行时中,也无法从该只读的全局列表中获得热更新的程序集数据,从而无法执行热更新。
40.但是,在il2cpp的运行时库中,为了节省内存,在获取程序集中的元数据类型时,引用保存元数据类型的字段并不直接指向一个元数据的内存指针,而是使用了int32_t 类型的程序集index作为指定该类型元数据的固定数组的索引。可以基于此,来实现运行时中元数据管理模块的改进,从而实现热更新的程序集的动态加载。
41.进一步的,在运行时加载热更新程序集时,基于与il2cpp运行时同样的工作原理,为该程序集assembly分配一个int32_t 类型的index,并对该index进行编码,例如,使得该index的高4位不为0。由于int32_t类型所支持的正整数范围为1~2,147,483,647,而程序集中元数据的类型字段的总量几乎不可能达到此范围的最大数量,即int32_t类型的高位在几乎所有的情况下并没有被使用,因此可以将该int32_t类型的高n位用作区分位,从而将热更新程序集与非热更程序集区分开来,其中n的取值由本领域技术人员根据实际情况来选择。例如,在执行热更新指令时,当识别到index的高4位不为0时,不再从全局程序集列表中获取热更新程序集的元数据,而是从动态加载的程序集中获取,即通过动态加载的热更新程序集管理动态的元数据信息,从而实现了il2cpp下的动态程序集加载管理功能。
42.具体的,获取il2cpp的运行时库中的getfielddefinitionfromindex函数,该函数用于获得目标程序集元数据的字段。在该函数中插入如下斜体代码,static const il2cppfielddefinition* getfielddefinitionfromindex(const il2cppimage* image, fieldindex index){
ꢀꢀꢀꢀ
if (huatuo:: isinterimage (image))
ꢀꢀꢀꢀ
{return huatuo::metadata::climetadata::getfielddefinitionfromencodeindex(index);
ꢀꢀꢀꢀ
}

//其它il2cpp代码}在函数getfielddefinitionfromindex中通过isinterimage(image)判断image的index的高4位,从而确定当前返回的应该是热更新程序集中的元数据还是非热更程序集中
的元数据,进而从对应的位置获得元数据字段的定义信息,为热更新的执行打下了基础。
43.在该步骤中,将热更新的程序集动态加载到il2cpp运行时,动态扩充了运行时的类型,进一步通过对程序集中元数据字段的index进行编码,对不同的程序集元数据的获取进行了区分,实现了热更新的准备。在该方式中,由于是将热更新程序集和主程序加载到同一运行时中,不存在现有技术中ilruntime与il2cpp运行时的区分,消除了类型系统不兼容问题,让热更新的代码与主程序代码在同一运行时中无缝运行,也大幅提升了内存和运行效率。同时,热更新的程序集由c#开发实现,与unity平台下应用开发所使用的语言相同,对研发人员来说不存在跨语言的问题,提高了开发效率。
44.步骤206:将热更新程序集methodinfo结构中的methodpointer指向il解释器的 execute 函数。
45.在步骤204中,已经实现了程序集的动态加载,使得主程序和热更新的程序集数据运行在同一运行时下。但是程序集中功能的执行是由函数来实现的,为了能够解释执行热更新程序集中的函数,还需要进一步的改进。
46.在符合clr规范的il2cpp运行时环境中,加载程序集时会将各种元数据信息加载到内存中对应的类型结构中,其中函数信息在运行时中的结构为:typedef struct methodinfo{
ꢀꢀꢀꢀ
il2cppmethodpointer methodpointer;
ꢀꢀꢀꢀ
invokermethod invoker_method;
ꢀꢀꢀꢀ
const char* name;
ꢀꢀꢀꢀ
il2cppclass *klass;
ꢀꢀꢀꢀ
const il2cpptype *return_type;
ꢀꢀꢀꢀ
const parameterinfo* parameters;
ꢀꢀꢀꢀ
union
ꢀꢀꢀꢀ
{
ꢀꢀꢀꢀꢀꢀꢀꢀ
const il2cpprgctxdata* rgctx_data; /* is_inflated is true and is_generic is false, i.e. a generic instance method */
ꢀꢀꢀꢀꢀꢀꢀꢀ
il2cppmetadatamethoddefinitionhandle methodmetadatahandle;
ꢀꢀꢀꢀ
};
ꢀꢀ…
} methodinfo;上述methodpointer字段指向了函数的实际地址,进一步的,将热更新程序集的methodpointer指向il解释器的 execute 函数。
47.步骤208:对程序集函数执行指令进行拦截,将热更新程序集函数的执行任务交给解释器执行。
48.在一种具体的实施方式中,在执行热更新程序集指令时,对运行时的函数getmethodpointer进行拦截,在函数中插入如下斜体代码:il2cppmethodpointer getmethodpointer(const il2cppimage* image, uint32_t token)
{if (huatuo::isinterimage(image))
ꢀꢀꢀꢀ
{
ꢀꢀꢀꢀꢀꢀꢀꢀ
return huatuo::metadata::climetadata::getmethodpointer(image, token);
ꢀꢀꢀꢀ
}}在isinterimage(image)函数中通过与步骤202中同样的方法判断当前加载的程序集是热更新还是非热更新程序集,若是热更新程序集则调用自定义getmethodpointer函数,从动态加载的程序集中获取函数的元数据methodinfo,将methodpointer 指向解释器的 execute 函数,从而成功的在运行时中将来自热更新程序集函数的执行任务交给了解释器。
49.进一步的,当解释器对热更新的程序集进行逐行解释,执行execute函数时,根据传入的函数参数methodinfo*获得methodinfo结构体中的字段methodmetadatahandle。
50.根据il2cpp中methodinfo的结构定义可以得知,变量methodmetadatahandle实际上为il2cppmethoddefinition数据类型,该数据类型的结构为:typedef struct il2cppmethoddefinition{
ꢀꢀꢀꢀ
stringindex nameindex;
ꢀꢀꢀꢀ
typedefinitionindex declaringtype;
ꢀꢀꢀꢀ
typeindex returntype;
ꢀꢀꢀꢀ
parameterindex parameterstart;
ꢀꢀꢀꢀ
genericcontainerindex genericcontainerindex;
ꢀꢀꢀꢀ
uint32_t token;
ꢀꢀꢀꢀ
uint16_t flags;
ꢀꢀꢀꢀ
uint16_t iflags;
ꢀꢀꢀꢀ
uint16_t slot;
ꢀꢀꢀꢀ
uint16_t parametercount;} il2cppmethoddefinition;。
51.在该数据结构定义中,包括一个uint32_t类型的token字段,通过该token字段可以获得函数的字节码信息,利用该函数的字节码信息,解释器的excute函数即可执行。
52.在该步骤中,通过对程序集加载过程的拦截,获取了为函数赋予指针methodpointer的过程,将来自热更新程序集函数的methodpointer 指向解释器的 execute 函数;进一步,将包含了字节码信息的methodinfo结构体通过参数传递给解释器的excute函数,从而完成了热更新程序集中函数的解释执行。
53.在上述实施例中,对il2cpp的结构进行改进,将一个仅支持aot静态编译的运行时改造为一个支持aot+解释器的运行时,实现了跨平台的高效热更新方案的基础;进一步地,通过对元数据index进行编码,实现了动态加载热更新的程序集动态库,扩充了运行时的元数据类型,实现了aot运行时的类型与热更新的程序集中的类型系统的统一,对于使用到泛
型和反射等动态机制的代码,不再会出现大量的不兼容问题;在函数的调用过程中,则通过对程序集加载过程的拦截,将来自热更新程序集的函数指向解释器,从而完成了热更新程序集中函数的解释执行,实现了函数的调用统一,保证了aot的c++函数和解释器函数之间运行的无缝性。
54.与上述方法实施例相对应,本技术还提供了一种用于unity的热更新装置的实施例,图4示出了本技术一个实施例的一种用于unity的热更新装置的结构示意图。如图4所示,该装置包括:aot编译器;il2cpp运行时环境;il解释器,用于对热更新的程序集代码进行解释执行;动态加载模块,用于动态加载热更新程序集到il2cpp运行时中;重定向模块,用于将热更新程序集methodinfo结构中的methodpointer指向il解释器的 execute 函数;拦截模块,用于对程序集函数执行指令进行拦截,将热更新程序集函数的执行任务交给解释器执行。
55.上述为本实施例的一种用于unity的热更新装置的示意性方案。需要说明的是,该用于unity的热更新装置的技术方案与上述的用于unity的热更新方法的技术方案属于同一构思,该用于unity的热更新装置的技术方案未详细描述的细节内容,均可以参见上述用于unity的热更新方法的技术方案的描述。
56.本技术一实施例中还提供一种计算设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机指令,所述处理器执行所述指令时实现所述的用于unity的热更新方法的步骤。
57.上述为本实施例的一种计算设备的示意性方案。需要说明的是,该计算设备的技术方案与上述的用于unity的热更新方法的技术方案属于同一构思,计算设备的技术方案未详细描述的细节内容,均可以参见上述用于unity的热更新方法的技术方案的描述。
58.本技术一实施例还提供一种计算机可读存储介质,其存储有计算机指令,该指令被处理器执行时实现如前所述用于unity的热更新方法的步骤。
59.上述为本实施例的一种计算机可读存储介质的示意性方案。需要说明的是,该存储介质的技术方案与上述的用于unity的热更新方法的技术方案属于同一构思,存储介质的技术方案未详细描述的细节内容,均可以参见上述用于unity的热更新方法的技术方案的描述。
60.上述对本技术特定实施例进行了描述。其它实施例在所附权利要求书的范围内。在一些情况下,在权利要求书中记载的动作或步骤可以按照不同于实施例中的顺序来执行并且仍然可以实现期望的结果。另外,在附图中描绘的过程不一定要求示出的特定顺序或者连续顺序才能实现期望的结果。在某些实施方式中,多任务处理和并行处理也是可以的或者可能是有利的。
61.所述计算机指令包括计算机程序代码,所述计算机程序代码可以为源代码形式、对象代码形式、可执行文件或某些中间形式等。所述计算机可读介质可以包括:能够携带所述计算机程序代码的任何实体或装置、记录介质、u盘、移动硬盘、磁碟、光盘、计算机存储
器、只读存储器(rom,read-only memory)、随机存取存储器(ram,random access memory)、电载波信号、电信信号以及软件分发介质等。需要说明的是,所述计算机可读介质包含的内容可以根据司法管辖区内立法和专利实践的要求进行适当的增减,例如在某些司法管辖区,根据立法和专利实践,计算机可读介质不包括电载波信号和电信信号。
62.需要说明的是,对于前述的各方法实施例,为了简便描述,故将其都表述为一系列的动作组合,但是本领域技术人员应该知悉,本技术并不受所描述的动作顺序的限制,因为依据本技术,某些步骤可以采用其它顺序或者同时进行。其次,本领域技术人员也应该知悉,说明书中所描述的实施例均属于优选实施例,所涉及的动作和模块并不一定都是本技术所必须的。
63.在上述实施例中,对各个实施例的描述都各有侧重,某个实施例中没有详述的部分,可以参见其它实施例的相关描述。
64.以上公开的本技术优选实施例只是用于帮助阐述本技术。可选实施例并没有详尽叙述所有的细节,也不限制该发明仅为所述的具体实施方式。显然,根据本技术的内容,可作很多的修改和变化。本技术选取并具体描述这些实施例,是为了更好地解释本技术的原理和实际应用,从而使所属技术领域技术人员能很好地理解和利用本技术。本技术仅受权利要求书及其全部范围和等效物的限制。
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1