zoukankan      html  css  js  c++  java
  • Lua热更系统

    1.介绍

       使用脚本开发游戏业务逻辑其中一个好处就是代码可线上热更,不停机修复bug。而热更代码的写法与需要被热更的文件的代码又有着密切的关系,本文介绍一种热更方法。

    2.热更原理

      Lua提供一个叫require的函数,实现文件的加载,require的作用可查看云风大大的参考手册说明  http://cloudwu.github.io/lua53doc/manual.html#pdf-require
    要热更一个已经被加载(require)过的模块,要做两件事件.

    1. 将package.loaded[filename] = nil, 将模块置空.

    2. 重新调用require,require(filename).

    如果要热更的模块里面所用到的都是全局变量,那么只需要这样写:

    global_var = global_var

    ok,新的模块内容就会重新被加载进内存了,而且全局变量也成功保留了热更前的值。

    然而每个文件里面只定义全局变量,会破坏模块的可读性,试想一下,定义了一个类,但它并没有成员变量,用到的变量全是全局变量,这是一种怎样的感受。
    所以我们要换一种写法,模块既可以有自己的变量,又可以被热更。

    3. 实现

      形如一个类既有成员变量,又有成员函数,要实现热更一个模块同时又保留其原有变量,我们可以把模块的变量定义和函数定义分开,分别写在两个文件。
    目录如下:

      data目录: modA.lua; modB.lua; modC.lua

           logic目录: modA.lua; modB.lua; modC.lua

    把模块的变量定义放在data文件夹,把模块函数的实现放在logic目录。

    下面是实现:

    1 -- data.modA
    2 local mod = {}
    3 -- 这里定义模块变量
    4 mod.players = {}
    5 mod.total_online = 0
    6 
    7 -- 最后记得return这个表
    8 return mod
     1 -- logic.lua
     2 local mod = require("data.modA")
     3 
     4 -- 定义函数
     5 function mod.login()
     6        -- xxxxxx
     7 end
     8 
     9 function mod.load_data()
    10       -- xxxxxxx
    11 end

    这里只是一个例子,logic.modA想要执行 `require("data.modA")` 成功,还要修改package.path,这个是Lua虚拟机启动时自己去定义了,这里不做讨论。
    这里把模块的变量和函数的定义分离了,我们只热更function目录下的文件,data目录下的则不管。
    热更文件的实现如下:

     1 -- require_ex.lua
     2 function require_ex(filename)
     3     local old_content
     4     if package.loaded[filename] then
     5         -- 把旧的模块保存起来
     6         old = package.loaded[filename]
     7         -- 然后package.loaded[filename]赋空
     8         package.loaded[filename] = nil
     9     end
    10          
    11      -- xpcall下执行require
    12     local ok,err = pcall(require, filename)
    13     if not ok then
    14         --热更失败,将旧值赋回去
    15         print("hotfix fail, err msg ",err)
    16         package.loaded[filename] = old_content
    17         return false
    18     end
    19 
    20     return true
    21 end

    切记: 重新require模块的时候,必须在pcall下执行,万一模块有语法错误,require挂掉的话,package.loaded[filename]就会一直为nil。当有其他文件需要执行 require(filename)的时候,则会报错,后面的逻辑无法执行。

    Coding Life
  • 相关阅读:
    Module build failed: TypeError: this.getResolve is not a function 安装node-sass运行报错
    RMAN Catalog 和 Nocatalog 的区别
    oracle 闪回区故障
    mysql windows 安装 错误
    git rejected
    oracle 计算机改名后监听无法启动
    mysql GTID
    java程序员技术范围
    activiti
    spring mybatis mysql 事务不起作用
  • 原文地址:https://www.cnblogs.com/lewiskyo/p/6160059.html
Copyright © 2011-2022 走看看