BZ易风

导航

 

LUA调用C#文件

C# 给Lua注入一个变量

c#脚本中

        LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
        //C# 给Lua注入一个变量  global.Set 向Global的表中注入一个变量
        //默认执行lua时,会索引到Global表
        global.Set("gameObject", gameObject);

lua脚本可以直接打印该变量

-- 当前ReviewC#脚本所挂的游戏物体的名字打印
print("Review ... ...: " .. gameObject.name)

LuaEnv.DoString()方法的第二个参数作用

c#脚本

//第二参数报错时: 提示作用
        XLuaMgr.Instance.LuaEnv.DoString("require('Review')", "Lua.Review");

LUA调用含有out、ref的方法

LuaOutRefFunction.lua

print("Lua Out Ref Function ... ...")

OutRefClass = CS.OutRefClass
local a = 1
-- C#的方法中的out参数,在lua中是以返回值的形式传出
-- 当方法本身有返回值时,out参数作为第二个及其之后的返回值传出
-- Lua调用C#带有out参数的方法时,out参数不需要传递参数,可以跳过,直接传递下一个
result, a = OutRefClass.Function(9,5)

print("result:", result)
print("a", a)


-- C#的方法中有ref参数,在lua中是以返回值的形式传出
-- 当方法本身有返回值时,ref参数作为第二个及其之后的返回值传出
-- Lua调用C#带有ref参数的方法时,ref参数需要传递参数的
local b = 1
result, b = OutRefClass.Function1(b, 6)

print("result:", result)
print("b:", b)

-- 可变参数的方法, xLua是支持的

LuaOutRefFunction.cs

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

public class LuaOutRefFunction : MonoBehaviour
{
    void Start ()
    {
        XLuaMgr.Instance.LuaEnv.DoString("require('LuaOutRefFunction')");
    }
}

[XLua.LuaCallCSharp]
public class OutRefClass
{

    public static string Function(int c, out int a, int b)
    {
        a = 10;
        Debug.Log("c:" + c);
        Debug.Log("b:" + b);
        return "str";
    }

    public static string Function1(ref int a, int b)
    {
        a = 10;
        Debug.Log("Function1 b:" + b);
        return "Function1";
    }

}

lua调用c#的枚举enum

LuaCallEnum.lua

print("Lua Call Enum ......")

-- C# HeroType.Warrior
-- Lua调用C#的枚举值  CS.命名空间.枚举类型.枚举值
-- C#的枚举的定义中,枚举值不要使用中文
local hType = CS.HeroType.Warrior

-- xLua提供了, 数字与字符串转换成枚举的方法
-- CS.命名空间.枚举类型.__CastFrom(数字或字符串)
-- 数字 2 转换成枚举, 不存在的int值,转换不会报错
hType = CS.HeroType.__CastFrom(2)

-- 字符串转换 Mage 转换成枚举, c#枚举项中不能有中文,如果有中文,调用时会出错
hType = CS.HeroType.__CastFrom("巫师")        --此处不会报错 可以赋值给hType,但是调用时会报错


-- 字符串转换 Mage 转换成枚举, 不存在的字符串, 转换会报错
hType = CS.HeroType.__CastFrom("Mage")


print(hType)
if hType == CS.HeroType.Warrior then
    print("战士")
elseif hType == CS.HeroType.Mage then
    print("法师")
elseif hType == CS.HeroType.Warlock then
    print("术士")
-- elseif hType == CS.HeroType.巫师 then            --CS.HeroType.巫师 会报错
--     print("巫师")
end

LuaCallEnum.cs

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

[XLua.LuaCallCSharp]
public enum HeroType
{
    /// <summary>
    /// 战士, 0
    /// </summary>
    Warrior,

    /// <summary>
    /// 法师, 1
    /// </summary>
    Mage,

    /// <summary>
    /// 术士, 2
    /// </summary>
    Warlock,

    巫师,
}

public class LuaCallEnum : MonoBehaviour
{
    void Start ()
    {
        XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallEnum')");
    }
}

Lua不支持typeof()方法, 但是XLua支持typeof()方法

LuaTypeof.lua

print("Lua Typeof")

GameObject = CS.UnityEngine.GameObject
Image = CS.UnityEngine.UI.Image
Color = CS.UnityEngine.Color

local obj = GameObject.Find("Canvas/Image")
--在xlua中是支持typeof关键字, 获取类型
local image = obj:GetComponent(typeof(Image))

--image.color = Color.red

image.color = Color(1,1,1, 0.5)

LuaTypeof.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LuaTypeof : MonoBehaviour
{

    // Use this for initialization
    void Start () {

        XLuaMgr.Instance.LuaEnv.DoString("require('LuaTypeof')");

        //GameObject obj = GameObject.Find("Canvas/Image");
        //Image image = (Image)obj.GetComponent(typeof(Image));
        //image.color = Color.red;

    }
    
    // Update is called once per frame
    void Update () {
        
    }
}

xlua调用c#委托

注意:xlua调用静态和非静态委托格式是一致的 都是CS.(命名空间.)类名.委托变量名()

LuaCallDelegate.lua

print("Lua Call Delegate ......")

function Func1()
    print("执行Lua Func1方法")
end

function Func2()
    print("执行Lua Func2方法")
end

-- 静态委托变量 非静态委托变量调用都是使用点的形式一样
-- Lua给C#的委托变量添加方法
CS.CallDelegate.action = Func1
-- Lua中没有 += 的复合赋值运算符,如果要 += 需要写出  a = a + b
-- 当委托变量为空时,只能直接赋值,不能使用 a = a + b的形式添加方法
CS.CallDelegate.action = CS.CallDelegate.action + Func2

-- Lua将委托变量设置为空的
CS.CallDelegate.action = nil

-- 直接赋值一个匿名字方法
CS.CallDelegate.action = function()
    print("执行Lua 匿名方法1111")
end

-- 叠加匿名字方法
CS.CallDelegate.action = CS.CallDelegate.action + function()
    print("执行Lua 匿名方法2222")
end

-- 调用委托, 调用委托时要注意判断是否是空的
if CS.CallDelegate.action then
    CS.CallDelegate.action()
end



-- C#调用泛型委托

function Func3(str)
    print("执行Lua Func3方法",type(str), str)
end

CS.CallDelegate.action1 = Func3

if CS.CallDelegate.action1 then
    CS.CallDelegate.action1("你好")
end

CS.CallDelegate.action2 = Func3

if CS.CallDelegate.action2 then
    CS.CallDelegate.action2(1.2)
end

LuaCallDelegate.cs

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

public class LuaCallDelegate : MonoBehaviour
{
    void Start ()
    {
        XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallDelegate')");
    }
}

[XLua.LuaCallCSharp]
public class CallDelegate
{
    public static Action action;

    public Action unStaticAction;

    public static Action<string> action1;
   
       //lua调用Action<float>的时候会报错
    //需要在Action<float>的类前加[CSharpCallLua]特性
    //但是Action<T> 是c#系统提供的类方法,不是自定义的 无法加[CSharpCallLua]特性
    //此时需要写一个列表,用来配置系统提供的方法加[CSharpCallLua]特性
    public static Action<float> action2;  
}

配置方法给系统类方法加[CSharpCallLuA]特性,因为是文件生成的时候激活下,放在Editor文件夹下

 

XLuaConfigList.cs

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

public static class XLuaConfigList 
{

    //创建一个Type类型的静态的List
    //通过这种方式,对cs_call_lua_list列表中的类型添加XLua.CSharpCallLua特性
    //使xLua能识别到要对其生成配置代码
    //当想要对系统C#的类, 或Unity的相关类添加给特性时,就可以使用这种方式
    [XLua.CSharpCallLua]
    public static List<System.Type> cs_call_lua_list = new List<System.Type>()
    {
        typeof(System.Action<float>),
        typeof(GameObject)
    };
}

xlua调用c#事件

注意:xlua调用静态和非静态事件格式是不一致的

静态以“.”点的方式:CS.(命名空间.)类名.委托变量名()

非静态需要实例化对象,然后以“:”冒号的方式:对象:委托变量名()

LuaCallEvent.lua

print("Lua Call Event ......")

function Func1()
    print("执行Lua Func1的方法")
end

function Func2()
    print("执行Lua Func2的方法")
end

-- Lua对事件进行添加方法与委托不一样
-- CS.类名.事件名("+", 要添加的方法名)
-- 不表示调用事件,而是对事件添加方法
CS.CallEvent.action("+", Func1)
CS.CallEvent.action("+", Func1)
CS.CallEvent.action("+", Func2)

-- 删除事件  CS.类名.事件名("-", 要添加的方法名)
CS.CallEvent.action("-", Func2)

-- 通过调用C#的执行事件的方法判断是否添加成功
CS.CallEvent.ExcuteStaticAction()


-- Lua对非静态事件添加方法
function Func3()
    print("执行Lua Func3的方法")
end

local ce = CS.CallEvent()
-- Lua添加非静态事件  对象:事件名("+", 要添加的方法名)
-- 对象:事件名("-", 要添加的方法名)
ce:unStaticAction("+", Func3)

ce:ExcuteUnStaticAction()

LuaCallEvent.cs

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

public class LuaCallEvent : MonoBehaviour
{
    void Start ()
    {
        XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallEvent')");
    }
}

[XLua.LuaCallCSharp]
public class CallEvent
{
    //类外部只能赋值,不能调用
    public static event System.Action action;

    public static void ExcuteStaticAction()
    {
        if (action != null)
        {
            action();
        }
    }


    public event System.Action unStaticAction;

    public void ExcuteUnStaticAction()
    {
        if (unStaticAction != null)
        {
            unStaticAction();
        }
    }
}

LuaBehaviors.cs配置

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

public class LuaBehaviour : MonoBehaviour
{
    //执行的Lua文件的名字
    public string luaFileName;

    private Action awake;
    private Action start;
    private Action update;
    private Action ondestroy;

    //定义提供了一个独立的存储区LuaTable, 用来存储当前的Lua执行时生成的变量和方法
    //与Global全局做区分
    private LuaTable scriptLua;

    private void Awake()
    {
        luaFileName = gameObject.name;          //如果lua文件和物体的名字一直时可以这么写
        string lua;
        //读取Lua文件的内容
        if (!XLuaMgr.Instance.LoadLuaString(luaFileName, out lua))
        {
            return;
        }

        //创建独立存储区表, 用来防止同名变量与全局Global出现冲突问题
        scriptLua = XLuaMgr.Instance.LuaEnv.NewTable();

        //当想要访问scriptLua表中某个变量或方法时,如果没有希望去Global中查找
        //使用元表来实现  通过元方法 __index, 当访问表中不存在的索引时, 会执行元表中的__index元方法
        //创建一个元表
        LuaTable meta = XLuaMgr.Instance.LuaEnv.NewTable();
        //在元表中添加元方法 __index 
        meta.Set("__index", XLuaMgr.Instance.LuaEnv.Global);
        //设置scriptLua的元表是meta, xLua中很多对Lua语法的解析在Global中,
        //必须设置当前独立存储区的scriptLua的元表__index指向Global, 否则会造成Lua语言运行错误
        scriptLua.SetMetaTable(meta);
        //释放元表的空间
        meta.Dispose();

        //将当前游戏物体注入到独立存储区scriptLua
        scriptLua.Set("gameObject", gameObject);
        scriptLua.Set("transform", transform);

        //执行当前Lua语言是, 将变量和方法注入到另外一个LuaTable中,不注入Global
        //将Lua语句中的变量与方法注入到scriptLua中
        //需要直接运行Lua文件的内容,不能通过require方法加载文件,导致变量注入失败
        XLuaMgr.Instance.LuaEnv.DoString(lua, luaFileName, scriptLua);

        //从当前独立存储区scriptLua获取Update方法
        scriptLua.Get("Awake", out awake);
        scriptLua.Get("Start", out start);
        scriptLua.Get("Update", out update);
        scriptLua.Get("OnDestroy", out ondestroy);
        PlayerPrefs.DeleteKey
        if (awake != null)
        {
            awake();
        }
    }

    private void Start()
    {
        if (start != null)
        {
            start();
        }
    }


    private void Update()
    {
        if (update != null)
        {
            update();
        }
    }

    private void OnDestroy()
    {
        if (ondestroy != null)
        {
            ondestroy();
        }
        awake = null;
        start = null;
        update = null;
        ondestroy = null;
        scriptLua.Dispose();
    }

}

实例:登录页面

 

 lua文件名和物体名一致,物体挂载luabehaviour配置

print("Login Panel ... ...")

require("UnityAPI")

local USERNAME_KEY = "Username"
local PASSWORD_KEY = "Password"

local userInput = nil
local pwdInput = nil
local tipText = nil
local rememberMeToggle = nil

-- 使用表来存储账号与密码, 键就是账号, 值就是密码
local userInfo = { admin = "666666",  player = "250"}

function Awake()
    -- 获取登录的按钮
    local loginObj = transform:Find("Window/Login")
    local loginButton = loginObj:GetComponent(typeof(Button))
    -- 对登录按钮添加事件
    loginButton.onClick:AddListener(ClickLogin)

    -- 查找两个输入框
    local userObj = transform:Find("Window/Username")
    userInput = userObj:GetComponent(typeof(InputField))
    -- 对输入框添加事件
    userInput.onValueChanged:AddListener
    (
        function(value)
            tipText.text = ""
        end
    )

    local pwdObj = transform:Find("Window/Password")
    pwdInput = pwdObj:GetComponent(typeof(InputField))
    pwdInput.onValueChanged:AddListener
    (
        function(value)
            tipText.text = ""
        end
    )

    local tipObj = transform:Find("Window/TipText")
    -- 当输入框内容发生改变时, 提示框内容消失
    tipText = tipObj:GetComponent(typeof(Text))

    local rememberMeObj = transform:Find("Window/RememberMe")
    rememberMeToggle =rememberMeObj:GetComponent(typeof(Toggle))
end

function Start()
    tipText.text = ""
    -- 每次进入要判断是否记录的上一次用户与密码
    if PlayerPrefs.HasKey(USERNAME_KEY) then
        userInput.text = PlayerPrefs.GetString(USERNAME_KEY)
    end

    if PlayerPrefs.HasKey(PASSWORD_KEY) then
        pwdInput.text = PlayerPrefs.GetString(PASSWORD_KEY)
    end
end

function ClickLogin()
    print("点击登录按钮: " .. userInput.text .. " -- " .. pwdInput.text)
    if userInput.text == "" or pwdInput.text == "" then
        tipText.text = "请输入用户名与密码"
        return
    end
    --验证用户名
    if userInfo[userInput.text] == nil then
        tipText.text = "用户名不存在"
        return
    end

    --验证密码
    if userInfo[userInput.text] ~= pwdInput.text then
        tipText.text = "密码错误"
        return
    end

    --判断是否需要记录
    if rememberMeToggle.isOn then
        -- print("记录用户名与密码")
        PlayerPrefs.SetString(USERNAME_KEY, userInput.text)
        PlayerPrefs.SetString(PASSWORD_KEY, pwdInput.text)
    else
        -- print("清楚记录的用户名与密码")
        PlayerPrefs.DeleteKey(USERNAME_KEY)
        PlayerPrefs.DeleteKey(PASSWORD_KEY)
    end

    --登录成功
    GameObject.Destroy(gameObject)

end

 

posted on 2021-03-18 19:10  BZ易风  阅读(263)  评论(0编辑  收藏  举报