Python在游戏中的热更新实现
作者:香菜聊游戏 发布时间:2022-04-05 14:10:15
目录
介绍:
原理:
1.标准import
2.reload函数
实现:
总结:
介绍:
热更新,就是在服务器不重启的的情况下,对游戏增加新的功能或者修复出现bug 的代码。游戏更新迭代速度快,催生了热更技术的需求,在我经历过的游戏项目中,无论是服务端还是客户端,版本的更新都是围绕着热更新,特别是现在游戏动辄几个G,每次让玩家下载完整的包不现实,随意游戏必须要支持热更。下面来谈一下客户端Python热更新的处理。
原理:
1.标准import
都知道Python提供了import可以导入一个标准的python模块,将模块载入内存,并加到sys.modules中。但是多次import同一模块只是将名称导入到当前的Local名字空间,也就是一个模块不会重复载入,所以想要热更靠这个特性是不行的。此路不通,请换个思路。
2.reload函数
reload()函数可以重新载入已经导入的模块,这样似乎就可以热更新Python的代码了。但是python原生的reload函数太过简单,不足以支撑游戏的热更新需求,主要原因有几个: reload重新加载的模块不会替换旧版本的模块,也就是已经引用的旧模块无法更新 同样因为不能旧对象的引用,使用from ... import ... 方式引用的模块同样不能更新 reloas(m)后,class及其派生class的实例对象,仍然使用旧的class定义。 同时加载模块失败时候,没有回滚机制,导致需要重新import该模块 因此,结合游戏的热更新需求,自定义合适的reload。新的自定义reload目的是为了达到在原程序不结束的情况下,让程序能动态加载改动后的代码。主要想达到下面两点: 提升开发效率 在游戏不重启的情况下修复紧急BUG
实现:
热更新最核心的需求就是让python解释器执行最新的代码,同时保证其他关联模块不会出现问题。对于刷新function,class内定义的method比较容易实现,但对于刷新module内定义的变量,class内定义的变量,还有新增加的成员变量,则需要有统一的约定。所以在实现热更新过程中,我们需要考虑好代码更新和数据更新这两点,下面罗列一下新的reload具备哪些特性:
1.更新代码定义(function/method/static_method/class_method) 不更新数据(除了代码定义外的类型都当作是数据) 在module中约定reload_module接口,class中约定reload_class接口,在这两个接口中手动处理数据的更新,还有更多的约定和接口待完成 替换函数对象的内容
# 用新的函数对象内容更新旧的函数对象中的内容,保持函数对象本身地址不变
def update_function(oldobj, newobj, depth=0):
setattr(oldobj, "func_code", newobj.func_code)
setattr(oldobj, "func_defaults", newobj.func_defaults)
setattr(oldobj, "func_doc", newobj.func_doc)
2.替换类的内容
# 用新类内容更新旧类内容,保持旧类本身地址不变
def _update_new_style_class(oldobj, newobj, depth):
handlers = get_valid_handlers()
for k, v in newobj.__dict__.iteritems():
# 如果新的key不在旧的class中,添加之
if k not in oldobj.__dict__:
setattr(oldobj, k, v)
_log("[A] %s : %s"%(k, _S(v)), depth)
continue
oldv = oldobj.__dict__[k]
# 如果key对象类型在新旧class间不同,那留用旧class的对象
if type(oldv) != type(v):
_log("[RD] %s : %s"%(k, _S(oldv)), depth)
continue
# 更新当前支持更新的对象
v_type = type(v)
handler = handlers.get(v_type)
if handler:
_log("[U] %s : %s"%(k, _S(v)), depth)
handler(oldv, v, depth + 1)
# 由于是直接改oldv的内容,所以不用再setattr了。
else:
_log("[RC] %s : %s : %s"%(k, type(oldv), _S(oldv)), depth)
# 调用约定的reload_class接口,处理类变量的替换逻辑
object_list = gc.get_referrers(oldobj)
for obj in object_list:
# 只有类型相同的才是类的实例对象
if obj.__class__.__name__ != oldobj.__name__:
continue
if hasattr(obj, "x_reload_class"):
obj.x_reload_class()
3.staticmethod
def _update_staticmethod(oldobj, newobj, depth):
# 一个staticmethod对象,它的 sm.__get__(object)便是那个function对象
oldfunc = oldobj.__get__(object)
newfunc = newobj.__get__(object)
update_function(oldfunc, newfunc, depth)
4.classmethod
def _update_classmethod(oldobj, newobj, depth):
oldfunc = oldobj.__get__(object).im_func
newfunc = newobj.__get__(object).im_func
update_function(oldfunc, newfunc, depth)
模块的更新也是相类似,就不一一粘贴了,只是在原来的reload基础上进行改良,对于模块热更新,还约定了一个reload_module接口,可以自定义数据的更新。 下面添加一些用例:
def x_reload_class(self):
""" 热更新后,每个重新对象的实例都会执行这个函数
由于新老对象的替换不会重新调用构造函数,因此有必要对热更新的类对象执行初始化逻辑
处理新老变量的修复,函数执行环境的修复
"""
self._new_var = 5000 # 新变量的初始化
self.runLogic() # 新修复的逻辑
总结:
只是在基础的reload模块上做了一些定制,让热更新更适合游戏的开发节奏,而不是简单暴力的reload模块
来源:https://juejin.cn/post/7022904502197944328
猜你喜欢
- 前言:Python在人工智能,后台服务等领域中得到了广泛应用。由于python有着大量的第三方开源包以及其易用的语言特性,这门语言在数据处理
- Python 输出 "Hello, World!",英文没有问题,但是如果你输出中文字符"你好,世界"
- 详解Golang 与python中的字符串反转在go中,需要用rune来处理,因为涉及到中文或者一些字符ASCII编码大于255的。func
- 在一些面试或者力扣题中都要求用双向链表来实现,下面是基于python的双向链表实现。一、构建链表节点class Node: &n
- 目标站点分析本次要抓取的目标站点为:中介网,这个网站提供了网站排行榜、互联网网站排行榜、中文网站排行榜等数据。网站展示的样本数据量是 :58
- 当我们导入的模型含有自定义层或者自定义函数时,需要使用custom_objects来指定目标层或目标函数。例如:我的一个模型含有自定义层“S
- 疑问在调用socket的时候,我们会使用到listen()函数,里面有个参数叫backlog, 例如:socket.listen(5). 那
- 几乎所有的微薄都提供了缩短网址的服务,其原理就是将一个url地址按照一定的算法生成一段字符串,然后加在一个短域名后面边成了一个新的url地址
- 代码# -*- coding:utf-8 -*-import osimport timef
- Python函数的定义定义函数,也就是创建一个函数,可以理解为创建一个具有某些用途的工具。定义函数需要用 def 关键字实现,具体的语法格式
- 之前需要做一些目标检测的训练,需要自己采集一些数据集,写了一个小demo来实现图片的采集使用方法:指定name的名称,name为分类的标签按
- <html> <head> <title>Untitled Document</title>
- 主要用于对字符串的加密,最常用的为MD5加密:import hashlibdef get_md5(data): obj = ha
- 如下所示:import pandas as pddf = pd.DataFrame([1, 2, 3, 4, 5], index=[10,
- 前言看到这篇文章我就默认你已经在你的电脑上使用 pipenv搭建好了虚拟环境并且设置好了开发环境(pycharm)。如果没有,请参照这篇文章
- 前言为什么会做这个?因为我们把word转化为pdf,wps默认转化为文字pdf,而图片pdf要会员。网上确实也有网站可以实现免费的,但是未必
- 前言首先图片格式转换的方法有很多,但是转二进制字节流的,我搜了一下午终于在 stackoverflow上搜到了 说一下为什么要在线转这个图片
- 了兑现我对大家的承诺,我们现在立即就将“借助数据库和ASP程序”编写出来的,可以同时适用于IIS和P
- 如何为XHTML做好准备,XHTML与HTML 4.01标准没有太多的不同。所以将你的代码升级至4.01是个不错的开始。HTML 4.01参
- 请先看看以下演示中的图案文字。这可不是图片效果,而是用CSS滤镜中的Chroma() 语句做成的文本文