文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Python在游戏中如何进行热更新处理

2023-06-25 10:43

关注

小编给大家分享一下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具备哪些特性:

更新代码定义(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)

替换类的内容

# 用新类内容更新旧类内容,保持旧类本身地址不变  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()

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)

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()      # 新修复的逻辑

看完了这篇文章,相信你对“Python在游戏中如何进行热更新处理”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网行业资讯频道,感谢各位的阅读!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯