Unity-xLua热更新总结

XLua 教程

执行 Lua 代码
using UnityEngine;
using XLua;

public class Helloworld01 : MonoBehaviour
{
	private LuaEnv luaEnv;   //对应一个Lua虚拟机,尽量全局唯一
    // Start is called before the first frame update
    void Start()
    {
		luaEnv = new LuaEnv();
		luaEnv.DoString("print('helloworld')");
		luaEnv.DoString("CS.UnityEngine.Debug.Log('Hello World')");
		luaEnv.DoString("CS.UnityEngine.MonoBehaviour.print('Hello World')");
	}

    
	private void OnDestroy() {
        //释放LuaEnv
		luaEnv.Dispose();
	}
}

输出结果:

LUA: helloworld
Hello World
Hello World

执行的 Lua 代码会再开都有 LUA: 标识。
后两句为在 Lua 中调用 Unity 的 API。

加载 Lua 文件

helloworld.lua.txt

print("helloworld")
a=2 b=3
print(a+b)
using UnityEngine;
using XLua;

public class Helloword02 : MonoBehaviour {
	LuaEnv luaEnv;
	// Start is called before the first frame update
	void Start() 
    {
		TextAsset ta= Resources.Load<TextAsset>("helloworld.lua");
		luaEnv = new LuaEnv();
        //1.通过Resources加载文本中的内容再去执行
        luaEnv.DoString(ta.text); 
        //2.系统内置方法
		luaEnv.DoString("require 'helloworld'"); //require不光引用还会执行,通过loder进行加载helloworld.lua,然后lua虚拟机执行代码
    }

	private void OnDestroy() 
    {
		luaEnv.Dispose();
	}
}

结果:

LUA: helloworld
LUA: 5
LUA: helloworld
LUA: 5
自定义 Loader
using System.IO;
using System.Text;
using UnityEngine;
using XLua;

public class CreateLoader : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv env = new LuaEnv();
        //添加自定义Loader
        env.AddLoader(MyLoader);

        env.DoString("require 'test007'");  //DoString 会依次传递给每一个Loader尝试
        env.Dispose();
    }

    //Loader方法
    private byte[] MyLoader(ref string filePath) {
        //输出filepath的路径
        //print("MyLoader receive filepath:"+filePath);
        //string str = "print('I am MyLoder')";

        string absPath = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";
        string str = File.ReadAllText(absPath);
        return Encoding.UTF8.GetBytes(str);
    }
}

结果:

LUA: test007
C# 调用 Lua

CSharpCallLua.lua.txt

print('there is CSharpCallLua.lua.txt')

a=100 
name="sunny"
isDie=false


person={
    name="sunny",age=24,12,2,2,2,2,2,2,3.3,true,"sunny",
    eat=function(self,a,b)
    print(a+b)
    print('我正在吃饭')
    end
}


--下面两种方式是相同的
--[[
    function person:eat(a,b)--默认代表一个self,代表当前的table
        print(a+b)
    end

     function person.eat(self,a,b)
        print(a+b)
     end
--]]


function add( )
print("add function")
end

function add1(a,b )
print(a+b)
return a+b,a,b
end
using System;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class CSharpCallLua : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();

        luaEnv.DoString("require 'CSharpCallLua'");

        print("---获取lua脚本内的变量属性---");
        int tempa = luaEnv.Global.Get<int>("a");//获取到CSharpCallLua.lua.txt中的a变量
        print(tempa);
        string tempname = luaEnv.Global.Get<string>("name");
        print(tempname);
        bool tempisdie = luaEnv.Global.Get<bool>("isDie");
        print(tempisdie);


        print("---获取lua脚本内的表(映射class或struct)---");
        Person p = luaEnv.Global.Get<Person>("person");  //通过值拷贝进行映射,比较消耗性能,修改这里的属性 ,不会影响lua里边的属性
        //lua脚本中不存在age2,所谓age2为默认值0,lua脚本中类似数组的数值也没有映射过来,因为没有对应类型,但是也没有报错,自由度很高
        print(p.name + "-" + p.age + "-" + p.age2);


        print("---获取lua脚本内的表(映射interface)---");
        //此部分在Interface声明添加CSharpCallLua不管用,依旧抛出异常InvalidCastException
        IPerson ip = luaEnv.Global.Get<IPerson>("person"); //相当于引用拷贝,修改这里的属性,lua里的属性也会改变
        print(ip.name + "-" + ip.age);
        ip.name = "sunny_cxr";
        //通过在lua中访问此字段看是否更改
        luaEnv.DoString("print(person.name)");
        //调用lua中的方法 
        ip.eat(10, 20);   //相当于ip.eat(ip,10,20);   lua中也需要传递当前对象


        print("---获取lua脚本内的表(映射到Dictionary<>,List<>)---");
        print("---Dictionary<>---");
        Dictionary<string, object> dic = luaEnv.Global.Get<Dictionary<string, object>>("person");
        foreach (string key in dic.Keys)
        {
            print(key + "-" + dic[key]);
        }
        print("---List<>---");
        List<object> list = luaEnv.Global.Get<List<object>>("person");
        foreach (object o in list)
        {
            print(o);
        }


        print("---获取lua脚本内的表(映射到LuaTable类)---");
        LuaTable tab = luaEnv.Global.Get<LuaTable>("person");
        print(tab.Get<string>("name"));
        print(tab.Get<string>("age"));
        print("table.length:" + tab.Length);


        print("---访问Lua中的全局函数(映射到delegate)---");
        Action act1 = luaEnv.Global.Get<Action>("add");
        act1();
        act1 = null; //若是不将委托置为空,当LuaEnv注销时act1依旧指向虚拟机中的方法,则会抛出异常

        //此部分在Add委托声明添加CSharpCallLua不管用,依旧抛出异常InvalidCastException
        Add add = luaEnv.Global.Get<Add>("add1");
        int resa; int resb;
        int res = add(100, 101, out resa, out resb);
        print("res:" + res);
        print("resa:" + resa);
        print("resb:" + resb);
        add = null;

        print("---访问Lua中的全局函数(映射到LuaFunction)---");
        LuaFunction func = luaEnv.Global.Get<LuaFunction>("add");
        object[] os = func.Call(1, 2);
        foreach (object o in os)
        {
            print(o);
        }

        luaEnv.Dispose();

    }
     
    [CSharpCallLua]
    delegate int Add(int a, int b,out int resa,out int resb);  //lua中的多返回值,可以映射到out、ref参数上

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


    // 用来进行映射的接口需要这个特性


    [CSharpCallLua]
    interface IPerson
    {
        string name { get; set; }
        int age { get; set; }
        void eat(int a, int b);
    }
}
Lua 调用 C#

LuaCallCSharp.lua.txt

--构造游戏物体,new对象
CS.UnityEngine.GameObject("new by lua")

print(CS.UnityEngine.Time.deltaTime)

CS.UnityEngine.Time.timeScale=0.5


local camera=CS.UnityEngine.GameObject.Find("Main Camera")
camera.name="update by lua"
local light=CS.UnityEngine.GameObject.Find("Directional Light")

--每次都通过CS.UnityEngine.GameObject访问Find方法比较耗费性能
--声明一次对CS.UnityEngine.GameObject的引用,以后直接使用即可
local gameObject=CS.UnityEngine.GameObject
local camera1=gameObject.Find("update by lua")
camera1.name="again update by lua"
local light1=gameObject.Find("Directional Light")
light1.name="平行光"

--调用成员方法时使用冒号
local cameraCom=camera:GetComponent("Camera")
gameObject.Destroy(cameraCom)
using UnityEngine;
using XLua;

[LuaCallCSharp]
enum EnemyType
{
    Normal,
    Hard,
    NB,
}

public class LuaCallCSharp : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();
        luaEnv.DoString("require 'LuaCallCSharp'");

        luaEnv.Dispose();
    }
}

使用 xLua 实现热更新的方案

  • 资源—打成AssetBundle
  • 代码—使用Lua编写
  1. 客户端启动连接服务器检查资源更新
  2. 如果更新就下载解压运行最新的
  3. 使用 MD5 校验检查文件是否更新,本地对比服务器的,文件是否最新,文件是否存在
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值