找回密码
 立即注册
查看: 335|回复: 0

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

[复制链接]
发表于 2021-8-11 09:04 | 显示全部楼层 |阅读模式
什么是热更新
热:就是刚出炉
简单来说就是当游戏某个功能出现bug,或者修改了某个功能,或者增加了某个功能的时候,我们不需要重新下载安装安装包,就可以更新游戏内容。
热更新的好处:不用浪费流量重新下载,不用通过商店审核更加快速,不用重新安装玩家可以更快体验到更新的内容
目前比较受欢迎的热更新方案:uLuatoluaxLua
热更新方案
这些热更新方案都是基于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.5local gameObject = CS.UnityEngine.GameObjectlocal camera = gameObject.Find("Main Camera")camera.name = "update by lua"


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

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 04:32 , Processed in 0.090299 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表