xLua游戏中的热更新(基于Unity2018)

2023-11-16

什么是热更新

热:就是刚出炉

简单来说就是当游戏某个功能出现bug,或者修改了某个功能,或者增加了某个功能的时候,我们不需要重新下载安装安装包,就可以更新游戏内容。

 

热更新的好处:不用浪费流量重新下载,不用通过商店审核更加快速,不用重新安装玩家可以更快体验到更新的内容

 

目前比较受欢迎的热更新方案:uLua tolua xLua

热更新方案

这些热更新方案都是基于Lua语言的,也可以叫做lua插件(可以运行lua,并实现了luaC#交互的插件)。

所以本质上这些热更新方案就是一个lua插件,可以运行lua,并实现了luaC#交互的插件。

 

1,(luainterface cs2lua tolua-->ulua(不再维护,转到主要维护tolua)

2tolua(基于tolua开发了luaframework

3slua代码质量好,性能比tolua

4C#lightLSharp同一个作者(商用比较少)

xLua

  xLua是Unity3D下Lua编程解决方案,自2016年初推广以来,已经应用于十多款腾讯自研游戏,因其良好性能、易用性、扩展性而广受好评。现在,腾讯已经将xLua开源到GitHub。

  2016年12月末,xLua刚刚实现新的突破:全平台支持用Lua修复C#代码bug。

  目前Unity下的Lua热更新方案大多都是要求要热更新的部分一开始就要用Lua语言实现,不足之处在于:

1、接入成本高,有的项目已经用C#写完了,这时要接入需要把需要热更的地方用Lua重新实现;

2、即使一开始就接入了,也存在同时用两种语言开发难度较大的问题;

3、Lua性能不如C#;

  xLua热补丁技术支持在运行时把一个C#实现(函数,操作符,属性,事件,或者整个类)替换成Lua实现,意味着你可以:

1、平时用C#开发;

2、运行也是C#,性能秒杀Lua;

3、有bug的地方下发个Lua脚本fix了,下次整体更新时可以把Lua的实现换回正确的C#实现,更新时甚至可以做到不重启游戏;

  这个新特性iOS,Android,Window,Mac都测试通过了,目前在做一些易用性优化。

什么是xLua

xLua为Unity、 .Net、 Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便的和C#相互调用。

 

创建工程导入xLua插件

通过xlua插件运行lua程序

创建一个Helloworld脚本,用来执行lua的输出语句

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class Helloworld01 : MonoBehaviour
{
    private LuaEnv luaEnv;
    void Start()
    {
        luaEnv = new LuaEnv();//创建lua运行环境
        luaEnv.DoString("print('Hello world')");//在()里面写lua语句
    }

    private void OnDestroy()
    {
        luaEnv.Dispose();//释放lua环境
    }
}

在lua中调用C#中的方法

另外一种输出方式,在lua中调用C#中的方法

luaEnv.DoString("CS.UnityEngine.Debug.Log('Hello world')");

加载运行lua源文件

首先创建一个helloworld.lua.txt的文件,必须为txt格式

然后创建一个Helloworld02的脚本进行加载

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class Helloworld02 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
       TextAsset ta = Resources.Load<TextAsset>("helloworld.lua");//helloworld.lua.txt
        LuaEnv luaEnv = new LuaEnv();
        luaEnv.DoString(ta.text);
        luaEnv.Dispose();
    }
}

通过内置的loader加载lua源文件

        luaEnv.DoString("require 'helloworld'");//loader进行加载helloworld.lua.txt  从Resources文件中进行加载

添加自定义的Loader方法

两只情况:一种是添加了一个自定义的Loader返回null并且DoString里面添加的是一个不存在的lua文件。它会返回错误。

    void Start()
    {
        LuaEnv env = new LuaEnv();
        env.AddLoader(MyLoader);
        env.DoString("require 'xxxxx'");
        env.Dispose();
           
    }

    private byte[] MyLoader(ref string filePath)
    {
        print(filePath);
        return null;
    }

另一种是添加了一个自定义的Loader返回lua语句的二进制并且DoString里面添加的是一个不存在的lua文件。它会执行自定义的Loader的输出。

    void Start()
    {
        LuaEnv env = new LuaEnv();
        env.AddLoader(MyLoader);
        env.DoString("require 'xxxxx'");
        env.Dispose();
           
    }

    private byte[] MyLoader(ref string filePath)
    {
        //print(filePath);
        string s = "print(123)";
        return System.Text.Encoding.UTF8.GetBytes(s);
    }

通过自定义Loader加载指定目录的Lua脚本

    void Start()
    {
        LuaEnv env = new LuaEnv();
        env.AddLoader(MyLoader);
        env.DoString("require 'test007'");
        env.Dispose();
           
    }

    private byte[] MyLoader(ref string filePath)
    {
        string adsPath = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";
        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(adsPath));
    }

C#访问Lua之访问Lua中的全局变量

    void Start()
    {
        LuaEnv env = new LuaEnv();
        env.DoString("require 'CSharpCallLua'");//调用完才能取得里面的变量
        int a = env.Global.Get<int>("a");//获取lua里面的全局变量a
        print(a);
        string str = env.Global.Get<string>("str");//获取lua里面的全局变量str
        print(str);
        bool isDie = env.Global.Get<bool>("isDie");//获取lua里面的全局变量isDie
        print(isDie);
        env.Dispose();
    }

C#访问Lua之访问Lua中的table(映射到class)

    void Start()
    {
        LuaEnv env = new LuaEnv();
        env.DoString("require 'CSharpCallLua'");//调用完才能取得里面的变量
        Person p = env.Global.Get<Person>("person");
        print(p.name + "-" + p.age);
        p.name = "Akimoto";
        env.DoString("print(person.name)");
        env.Dispose();
    }

    class Person
    {
        public string name;
        public int age;
    }

这种方式的访问,修改p的值不会影响到lua里面的表的属性

C#访问Lua之访问Lua中的table(映射到interface)

    [CSharpCallLua]
    public interface IPerson
    {
        string name { get; set; }
        int age { get; set; }
    }

        IPerson p = env.Global.Get<IPerson>("person");
        print(p.name);

映射到interface修改p中的属性,lua中的原table也会发生变化

C#访问Lua之通过Dictionary或者List

        //通过DIctionary,List
        //Dictionary<string, object> dict = env.Global.Get<Dictionary<string, object>>("person");
        //foreach (string key in dict.Keys)
        //{
        //    print(key + " " + dict[key]);
        //}

        List<object> list = env.Global.Get<List<object>>("person");
        foreach (object o in list)
        {
            print(o);
        }

C#访问Lua之通过LuaTable访问table

        //通过LuaTable类 比较慢
        LuaTable luaTable = env.Global.Get<LuaTable>("person");
        print(luaTable.Get<string>("name"));
        print(luaTable.Get<int>("age"));

C#访问Lua中的全局function(第一种方式)

使用委托来获取

        //访问lua中的全局函数
        //Action act1 = env.Global.Get<Action>("add");
        //act1();
        Add add = env.Global.Get<Add>("add");
        add(1, 2);
        env.Dispose();
    }

    [CSharpCallLua]
    delegate void Add(int a, int b);

通过LuaFunction访问Lua中的全局函数

        //使用LuaFunction来映射全局函数
        LuaFunction func = env.Global.Get<LuaFunction>("add");
        func.Call(1, 2);
        env.Dispose();

在Lua中new C#对象(创建游戏物体)

创建一个lua文件

CS.UnityEngine.GameObject()

创建一个C#脚本

    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();

        luaEnv.DoString("require 'LuaCallCSharp'");
    }

Lua访问C#静态属性和方法

修改lua代码

print(CS.UnityEngine.Time.deltaTime)

CS.UnityEngine.Time.timeScale = 0.5

local gameObject = CS.UnityEngine.GameObject

local camera = gameObject.Find("Main Camera")

camera.name = "update by lua"

Lua访问C#成员属性和方法

local cameraCom = camera.GetComponent(camera,"Camera")
gameObject.Destroy(cameraCom)

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

xLua游戏中的热更新(基于Unity2018) 的相关文章

随机推荐

  • C# 导出 Excel 方法

    第一种 使用 Microsoft Office Interop Excel dll public void ExportExcel DataTable dt if dt null Microsoft Office Interop Excel
  • 关键词生成器在线-在线免费关键词生成器

    关键词生成 什么是关键词生成 关键词生成就是根据你输入的一个关键词生成成千上百的核心关键词 围绕着你输入的核心词来生成的 优先生成大量用户搜索的关键词 今天就给大家分享一款免费关键词生成工具 关键词生成的来源主要是用户都在搜索的词 相关搜索
  • CentOS-8-x86_64-1905安装

    CentOS 8 x86 64 1905安装 安装前准备 VMware Workstation 点击下载虚拟机软件 VMware Workstation是一款功能强大的桌面虚拟计算机软件 提供用户可在单一的桌面上同时运行不同的操作系统 和进
  • Crazy Thairs【树状数组+高精度+DP思想】

    题目链接 POJ 3378 题意 有N个点 问的是要求组成一个长度为5的上升子序列的组成有多少种 最搞事情的是这道题不用取模 所以 是一定会爆long long的 首先 很容易想到一点就是我们可以开一个dp maxN 5 表示的是 dp i
  • Vagrant学习笔记:搭建K8s集群

    通常情况下 我们在使用VMware VirtualBox这一类虚拟机软件创建虚拟开发环境时 往往需要经历寻找并下载操作系统的安装镜像文件 然后根据该镜像文件启动的安装向导一步一步地安装与配置操作系统 最后还需要从零开始安装开发与运维工具 整
  • 计算机考研复试机试怎么速成,西安电子大学计算机考研复试机试(2019)+ 学长讲解(6)+ 作业...

    学长讲的就是算法笔记的入门算法 作业1 链接 https www nowcoder com questionTerminal 0f64518fea254c0187ccf0ea05019672 来源 牛客网 有一个网络日志 记录了网络中计算任
  • Java各种集合判空总结

    目录 集合判空 CollectionUtils isEmpty推荐 原始判断 isEmpty 其他 数组判空 集合判空 CollectionUtils isEmpty推荐 这个使用到了spring的工具类 需要提前引入依赖 import o
  • 机器学习2018-12-28

    机器学习 组成 主要任务 分类 classification 将实例数据划分到合适的类别中 应用实例 判断网站是否被黑客入侵 二分类 手写数字的自动识别 多分类 回归 regression 主要用于预测数值型数据 应用实例 股价价格波动的预
  • 用编程器免拆夹子刷斐讯K2 K2P解决难搞固件 刷BREED 无损原EEPROM

    文章中放的几个地址都是思路来源 感谢各路大神原帖子的思路 因为我刷机时候没有拍照 只好借用各位大佬的图来说明步骤 我做一下整理会放出本篇刷机流程 很简单 K2 22 6 532 231软件版本已经无解 UBOOT等可以软刷的方式都被堵死 编
  • .NET编程——利用C#实现TCP协议的异步通信Socket套接字(WinForm)

    本文将介绍利用基于TCP通信协议的Socket实现服务器与客户端之间的数据传输 目录 前言 计算机通信 创建服务器 服务器通信 创建客户端 客户端通信 前言 TCP IP Transmission Control Protocol Inte
  • 【编码-校验码】奇偶校验码

    https zhuanlan zhihu com p 26509678 引自原文 1 定义 奇偶校验位 英语 Parity bit 或校验比特 check bit 是一个表示给定位数的二进制数中1的个数是奇数还是偶数的二进制数 奇偶校验位是
  • 炫酷的Android智能下拉刷新框架,值得一看

    1 Android智能下拉刷新框架 SmartRefreshLayout 支持所有的 View AbsListView RecyclerView WebView View 和多层嵌套的视图结构 支持自定义并且已经集成了很多炫酷的 Heade
  • BRDF详解

    光照模型主要分为三类 测量模型 经验模型和基于物理的分析模型 在计算机图形学中介绍的光照模型为经验模型中的Phong模型 也就是本人理解的 根据点距光源的位置 入射角度等信息计算的 反射强度 包括漫反射强度 镜面反射强度 但是Phong模型
  • 《effective c++》笔记

    序 1 object 在 object oriented技术中的真正意义是 物件 物体 而非 对象 目标 导读 1 术语 1 声明式 告诉编译器名称和类型 但略去细节 std size t numDigit int number std命名
  • 软工导论知识框架(六)面向对象分析

    前言 绘制各种类型的图是重点 对于面向对象建模中需要绘制的图总结在第五期中 软工导论知识框架 五 面向对象方法学 一 分析过程 1 获取需求 与用户交谈 向用户提问题 参观用户的工作流程 观察用户的操作 向用户群体发调查问卷 与同行 专家交
  • 【满分】【华为OD机试真题2023 JAVA&JS】查找重复代码

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 查找重复代码 时间限制 1s 空间限制 32MB 限定语言 不限 题目描述 小明负责维护项目下的代码 需要查找出重复代码 用以支撑后续的代码优化 请你帮助小明找出重复的代码 重复
  • 使用IntelliJ IDEA查看类的继承关系图形

    最近正好也没什么可忙的 就回过头来鼓捣过去的知识点 到Servlet部分时 以前学习的时候硬是把从上到下的继承关系和接口实现记得乱七八糟 这次利用了IDEA的diagram 结果一目了然 也是好用到炸裂 就此分享 1 查看图形形式的继承链
  • Golang基础 流程控制 条件判断

    条件判断 01 条件判断 if 02 分支选择 switch 03 异步处理 select 参考资料 条件语句一般指定一个或多个条件 并通过测试条件是否为 true 来决定是否执行指定语句 并在条件为 false 的情况在执行另外的语句 0
  • 你得学会并且学得会的Socket编程基础知识

    这一篇文章 我将图文并茂地介绍Socket编程的基础知识 我相信 如果你按照步骤做完实验 一定可以对Socket编程有更好地理解 本文源代码 可以通过这里下载 http files cnblogs com chenxizhang Socke
  • xLua游戏中的热更新(基于Unity2018)

    什么是热更新 热 就是刚出炉 简单来说就是当游戏某个功能出现bug 或者修改了某个功能 或者增加了某个功能的时候 我们不需要重新下载安装安装包 就可以更新游戏内容 热更新的好处 不用浪费流量重新下载 不用通过商店审核更加快速 不用重新安装玩