[Unity XLua]热更新XLua入门(一)-基础篇

2023-11-20

Aladdin_XLua

前言

前段时间腾讯开源了一个内部热更框架XLua在Unity开发群里引起一阵热议,也受到广大开发者的热捧,然后我当然也抱着好奇的心去学习学习。后面也会将扩展之后的工程放在git上,大家一起学习交流!在此感谢XLua作者创造出这么好用的框架!

相关链接

  1. XLua源码

  2. C#->Lua开源工具 
    可以将C#转化成lua并且具有

  3. 相关介绍文章 
    https://www.oschina.net/news/80638/c-net-lua-unity3d

  4. 知乎热议

个人对XLua看法

  1. 简洁易用,容易上手
  2. 可扩展性高,添加自定义的CS模块或者第三方插件非常方便
  3. 大厂维护,可靠
  4. 特色:HotFix 
    关于这个HotFix是其他热更lua框架所不具备的,也是他最大的优势和特色之一,原理就是通过特性标记然后在IL逻辑层判断修改逻辑,使程序支持热更的lua逻辑代码而不是走之前的C#逻辑

自己扩展XLua支持NGUI开发

现在开源热更Lua框架都很少支持NGUI了,可能现在趋势都是用原生的UGUI,但估计还有一些NGUI粉喜欢用NGUI开发,毕竟NGUI用了很长时间,XLua例子里面已经支持了lua使用UGUI,这里我就自己补充让它支持NGUI开发。后续我也会多添加一些UGUI的例子。先看看扩展的NGUI做的界面效果图,然后下面再讲解怎么让XLua支持第三方插件。

效果图

这里写图片描述

快速上手

在学习一个东西之前最好先学习一下XLua作者辛辛苦苦写的那些多教程文档,包括案例以及wiki和issu,如果还有什么不明白的地方可以在加入文章最后的群我们一起交流学习。

1.自定义C#类供Lua访问

这里可以学习一下作者写的Test中的例子,还是比较详细,但我还是想记录一下我自己尝试的过程。

(1)特性方式

XLua支持使用特性标签让自定义的类可供Lua访问 
C#:

public class CSModelWithAttribute
{
    public static void SayHello1()
    {
        Debug.Log("Hello Aladdin_XLua, I am static model function");
    }
    public void SayHello2()
    {
        Debug.Log("Hello Aladdin_XLua, I am model function");
    }
    public void SayHello3(string s)
    {
        Debug.Log("Hello Aladdin_XLua, I am model function whih param:" + s);
    }

    public string SayHello4(string s)
    {
        Debug.Log("Hello Aladdin_XLua, 我是具有返回值的CS方法:" + s);
        return "你好,我获得了lua,我是C#";
    }

    public void SayHelloWithRefParam(ref string s)
    {
        Debug.Log("传入的参数是:" + s);
        s = "Hello 我是C#";
    }

    public string SayHelloWithRefParamAndReturnString(ref string s)
    {
        Debug.Log("传入的参数是:" + s);
        s = "Hello 我是C#";
        return "我是返回的字符串";
    }

    public void SayHelloWithOutParam(out string s)
    {
        s = "Hello,我是C#";
        Debug.Log("Hello Aladdin_XLua, I am model function whih out param:" + s);
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

添加上特性标签之后,程序在启动的会自动查找具有特性标记的类然后搜集进入lua栈,使得我们可以用Lua访问自定义的C#类和方法。

Lua访问:

using UnityEngine;
using System.Collections;
using XLua;
public class SelfExampleSrc : MonoBehaviour
{
    LuaEnv luaenv = new LuaEnv();
    void Start()
    {
        luaenv.DoString(@"

            print('Lua访问特性标记的对象方法')
            local luaM2 = CS.CSModelWithAttribute
            local luaO2 = luaM2()
            luaM2:SayHello1()
            luaO2:SayHello2()
            luaO2:SayHello3('我是阿拉丁')  --读者反馈新增一个C#方法 PC不需要重新 Generate,安卓、ios需要

            --测试字符串返回
            local value = luaO2:SayHello4('你好,我是lua')
            print(value)                              

            --测试ref
            local inputValue = '你好,我是lua'
            local outputValue = luaO2:SayHelloWithRefParam(inputValue)
            print(outputValue)                          --lua是通过字符串返回

            local outValue1,outValue2 = luaO2:SayHelloWithRefParamAndReturnString(inputValue)
            print(outValue1)
            print(outValue2)

            --测试out
            inputValue = '我是测试lua'
            outputValue = luaO2:SayHelloWithOutParam(inputValue)
            print(outputValue)

            local luaM3 = CS.CSModelTest
            local luaO3 = luaM3()
            luaO3.TestDelegate('lua中测试委托')


            luaO3.onClick = function(obj)
                print('hello 我是lua')
                print(obj)
            end
            luaO3.onClick('我是lua')
        ");
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
(2)wrap方式

如果是我们自己写的C#代码,我们可以通过第一种方式添加特性来让Lua支持也是比较方便,如果是用的开源第三方插件,我们如何快速的让XLua支持,就可以用过Generate Wrap的方式,这一点也是其他lua框架所采取的策略。

a)有命名空间的类

C#:

namespace Aladdin_XLua
{
    public class CSModel
    {
        public void SayHello()
        {
            Debug.Log("Hello Aladdin_XLua");
        }
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Lua:

print('Lua访问有命名空间的对象/静态方法')
local luaModel = CS.Aladdin_XLua.CSModel
local luaObj = luaModel()
luaObj:SayHello()
 
 
  • 1
  • 2
  • 3
  • 4

luaModel是C#类,下面luaObj是类生成的对象,最后是访问对象方法,关于Lua冒号调用和点调用的区别:冒号调用默认传入了self参数,不清楚的可以百度相关文章。

b)无命名空间的类

C#:

public class CSModelWidhoutNameSpace
{
    public void SayHello()
    {
        Debug.Log("Hello Aladdin_XLua without Namespace");
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Lua:

print('Lua访问无命名空间的对象方法')
local luaM = CS.CSModelWidhoutNameSpace
local luaO = luaM()
luaO:SayHello()
 
 
  • 1
  • 2
  • 3
  • 4

如果没有命名空间的话直接CS后面就是类名,其实CS也是一个更外面一层的命名空间,只不过是作者帮我们分装的。

3)委托类型

C#:

public class CSModelTest
{
    public SelfVoidDelegate onClick;
    public delegate void SelfVoidDelegate(GameObject go);
    void OnClick() { Debug.Log("测试"); }

    public Action<string> TestDelegate = (param) =>
    {
        Debug.Log("TestDelegate in c#:" + param);
    };
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

委托其实也是跟Class平级的,委托也是一种类型,所以我们也需要对它像对待类那样处理,通过添加特性标记或者通过Wrap方式处理,这里委托是放在类里面,其实也可以直接放在命名空间下面,.NET库是这样操作的,但我们看NGUI源码会发现,NGUI源码都是这样操作的,比如按钮的onClick事件,看它的委托类型VoidDelegate就会发现也是这样操作的,所以我这里例子也放在类的里面。

C#

public class CSModelTest
{
    public SelfVoidDelegate onClick;
    public delegate void SelfVoidDelegate(GameObject go);
    void OnClick() { Debug.Log("测试"); }

    public Action<string> TestDelegate = (param) =>
    {
        Debug.Log("TestDelegate in c#:" + param);
    };
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Lua:

local luaM3 = CS.CSModelTest
local luaO3 = luaM3()
luaO3.TestDelegate('lua中测试委托')

luaO3.onClick = function(obj)
    print('hello 我是lua')
    print(obj)
end
luaO3.onClick('我是lua')
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
4)带有ref out 参数的函数如何处理

因为Lua是弱类型没有C#那么多类型,有时候一些参数可能就不太好处理,比如C#的不同类型参数的重载,lua就不太好处理,这里可以查看XLua中的issues,作者有一个问题的相关解答。下面我举例ref和out参数类型的函数Lua如何访问。 
C#:

public void SayHelloWithRefParam(ref string s)
{
    Debug.Log("传入的参数是:" + s);
    s = "Hello 我是C#";
}

public string SayHelloWithRefParamAndReturnString(ref string s)
{
    Debug.Log("传入的参数是:" + s);
    s = "Hello 我是C#";
    return "我是返回的字符串";
}

public void SayHelloWithOutParam(out string s)
{
    s = "Hello,我是C#";
    Debug.Log("Hello Aladdin_XLua, I am model function whih out param:" + s);
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

Lua:

--测试ref
local inputValue = '你好,我是lua'
local outputValue = luaO2:SayHelloWithRefParam(inputValue)
print(outputValue)                          --lua是通过字符串返回

local outValue1,outValue2 = luaO2:SayHelloWithRefParamAndReturnString(inputValue)
print(outValue1)
print(outValue2)

--测试out
inputValue = '我是测试lua'
outputValue = luaO2:SayHelloWithOutParam(inputValue)
print(outputValue)
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

一开始我测试的时候是本以为lua调用ref传入的参数,也会返回出修改的结果,但出乎我的意料,并没能修改,经过作者提示,lua是通过返回值返回的ref参数,如果函数本身就有返回值,那么最后一个参数是返回的ref或者out参数,这个读者可以尝试一下。

运行结果

这里写图片描述

关于Wrap

Wrap是C#跟Lua之间的一个桥梁,Lua想要访问C#必须要用过Wrap访问,相信看过其他Lua框架的这一点应该不陌生,XLua对生成Wrap也是非常方便。

我们只要新建一个类然后继承一个GenConfig的接口,下面是接口内容,关于这几个类型XLua文档中也有介绍,我们只需要把自定义的类添加到LuaCallCSharp集合中即可,然后点击Generate就会自动帮我们生成对应的Wrap文件

//注意:用户自己代码不建议在这里配置,建议通过标签来声明!!
    public interface GenConfig 
    {
        //lua中要使用到C#库的配置,比如C#标准库,或者Unity API,第三方库等。
        List<Type> LuaCallCSharp { get; }

        //C#静态调用Lua的配置(包括事件的原型),仅可以配delegate,interface
        List<Type> CSharpCallLua { get; }

        //黑名单
        List<List<string>> BlackList { get; }
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

当然作者也说了,我们自定的C#代码最好不要通过这种方式,我这里只是演示如何添加,下面会说第三方插件通过这话总方式支持。 
C#:

public static class AladdinGenConfig
{
    //lua扩展第三方或者自定义类库
    public class LuaCallCSharpExtern : GenConfig
    {

        public List<Type> LuaCallCSharp
        {
            get
            {
                return new List<Type>()
                {
                    typeof(CSModelWidhoutNameSpace),
                    typeof(CSModel),
                    typeof(CSModelTest),
                }
            }
        }
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
2.NGUI扩展

正如上图所示的效果,下面讲述一下我是如何支持NGUI扩展的,也参考了作者UGUI的一个例子修改的。

a)生成Wrap接口

这一步上上面说的一样,只要把NGUI的组件类全部都添加到LuaCallCSharp列表中然后Generate一下即可,这里要注意的是组件中委托类型也需要添加进去。

b)搭建两个UI界面,UI逻辑接口用C#,Lua是调用逻辑调用界面中C#的方法。

这里写图片描述 
这里写图片描述

C#: 
购买

using UnityEngine;
using System.Collections;
using XLua;
public class AsyncBuy : MonoBehaviour
{
    LuaEnv luaenv = null;

    void Start()
    {
        luaenv = new LuaEnv();
        luaenv.DoString("require 'async_buy'");
    }

    // Update is called once per frame
    void Update()
    {
        if (luaenv != null)
        {
            luaenv.Tick();
        }
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Panel逻辑:

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

public class MessagePanel : MonoBehaviour
{
    /// <summary>
    /// 显示对话弹框
    /// </summary>
    /// <param name="message"></param>
    /// <param name="title"></param>
    /// <param name="onFinished"></param>
    public static void ShowAlertPanel(string message, string title, Action onFinished = null)
    {
        Debug.Log("显示提示弹框");
        var rootPanel = GameObject.Find("Panel").transform;
        var alertPanel = rootPanel.Find("AlertPanel");
        if (alertPanel == null)
        {
            alertPanel = (Instantiate(Resources.Load("AlertPanel")) as GameObject).transform;
            alertPanel.gameObject.name = "AlertPanel";
            alertPanel.SetParent(rootPanel);
            alertPanel.localPosition = Vector3.zero;
            alertPanel.localScale = Vector3.one;
        }
        alertPanel.Find("Title").GetComponent<UILabel>().text = title;
        alertPanel.Find("Content").GetComponent<UILabel>().text = message;
        alertPanel.gameObject.SetActive(true);
        if (onFinished != null)
        {
            var buyBtn = alertPanel.Find("BtnBuy").gameObject;
            buyBtn.SetActive(true);
            var button = buyBtn.GetComponent<UIButton>();
            UIEventListener.Get(buyBtn).onClick = go =>
            {
                onFinished();
                alertPanel.gameObject.SetActive(false);
            };
        }
    }

    /// <summary>
    /// 显示确认弹框
    /// </summary>
    /// <param name="message"></param>
    /// <param name="title"></param>
    /// <param name="onFinished"></param>
    public static void ShowConfirmPanel(string message, string title, Action<bool> onFinished = null)
    {
        var rootPanel = GameObject.Find("Panel").transform;
        var confirmPanel = rootPanel.Find("ConfirmPanel");
        if (confirmPanel == null)
        {
            confirmPanel = (Instantiate(Resources.Load("ConfirmPanel")) as GameObject).transform;
            confirmPanel.gameObject.name = "ConfirmPanel";
            confirmPanel.SetParent(rootPanel);
            confirmPanel.localPosition = Vector3.zero;
            confirmPanel.localScale = Vector3.one;
        }
        confirmPanel.Find("Title").GetComponent<UILabel>().text = title;
        confirmPanel.Find("Content").GetComponent<UILabel>().text = message;
        confirmPanel.gameObject.SetActive(true);
        if (onFinished != null)
        {
            var confirmBtn = confirmPanel.Find("BtnBuy").GetComponent<UIButton>();
            var cancelBtn = confirmPanel.Find("CancelBuy").GetComponent<UIButton>();

            UIEventListener.Get(confirmBtn.gameObject).onClick = go =>
            {
                onFinished(true);
                confirmPanel.gameObject.SetActive(false);
            };

            UIEventListener.Get(cancelBtn.gameObject).onClick = go =>
            {
                confirmPanel.gameObject.SetActive(false);
            };
        }
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

Lua: 
lua文件放在对应的Resources下即可 
async_buy.lua


local util = require 'xlua.util'
local message_panel = require 'message_panel'

-------------------------async_recharge-----------------------------
local function async_recharge(num, cb) --模拟的异步充值
    print('requst server...')
    cb(true, num)
end

local recharge = util.async_to_sync(async_recharge)
-------------------------async_recharge end----------------------------
local buy = function()
    message_panel.alert("余额提醒","您余额不足,请充值!")
    if message_panel.confirm("确认充值10元吗?","确认框" ) then
        local r1, r2 = recharge(10)
        print('recharge result', r1, r2)
        message_panel.alert("提示","充值成功!")
    else
        print('cancel')
        message_panel.alert("提示","取消充值!")
    end
end

CS.UIEventListener.Get(CS.UnityEngine.GameObject.Find("BtnBuy").gameObject).onClick = util.coroutine_call(buy)

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

message_panel.lua


local util = require 'xlua.util'

local sync_alert = util.async_to_sync(CS.MessagePanel.ShowAlertPanel)
local sync_confirm = util.async_to_sync(CS.MessagePanel.ShowConfirmPanel) 

--构造alert和confirm函数
return {
    alert = function(title, message)
        if not message then
            title, message = message, title
        end
         sync_alert(message,title)
    end;

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

[Unity XLua]热更新XLua入门(一)-基础篇 的相关文章

  • Lua中字符串的串联

    在许多语言中 您可以在变量赋值时连接字符串 我有一个使用 Lua 编程语言的场景 我需要将命令的输出附加到现有变量 Lua 中是否有与以下示例等效的功能 其他语言的例子 PERL filename checkbook filename tm
  • proxy_pass 不使用 /etc/hosts 解析 DNS

    在 Nginx 中proxy pass指令未使用以下命令解析 DNS etc hosts文件 有什么方法可以实现这种可能性 也许利用 Lua 作为最后的手段 如果您有一台带有 systemd 的服务器 您可以使用它附带的名称服务器 syst
  • 代码说“尝试比较数字<=实例”

    It says Players ninjafox56 PlayerGui Shop ShopGui LightSide ChooseSideL 5 尝试比较数字 Rank game Players LocalPlayer leadersta
  • 错误 main.lua:23:尝试索引 upvalue 'Menu' (布尔值)

    我正在尝试用 lua 和 love2d 制作一个主菜单 这是我第一次这样做 遗憾的是没有关于此事的教程 所以我自己尝试了一下 我一直遇到这个错误 我不知道如何解决它 请帮助 完整错误消息 错误main lua 23 尝试索引upvalue
  • 如何加载目录中的所有文件?

    正如标题所说 如何加载目录中的每个文件 我对c 和lua都感兴趣 编辑 对于 Windows 我很高兴能得到一些真正的工作代码 尤其是 lua 我可以用 boost filesystem for c 来做 对于 Lua 你需要模块Lua文件
  • 迭代包括空行在内的行

    给定一个带有一些空行的多行字符串 我如何在Lua中迭代行包括空行 local s foo nbar n njim for line in magiclines s do print line and blank or line end gt
  • Lua:“拖动”数组中的元素序列

    我正在尝试创建一个函数 将连续数量的元素 拖动 到数组中的新位置 并限制为数组的当前大小 其他项目应该围绕 拖动 的项目晃动 例如 如果我的数组有 7 个元素 并且我想拖动中间的三个 1 2 3 4 5 6 7 lt keys a b C
  • 使用 OOP 的闭包方法时如何实现受保护的成员?

    现在我正在使用实施 OOP 的闭包 http lua users org wiki ObjectOrientationClosureApproach在卢阿 下面是一个简短的示例 我的问题发生在尝试实施时stronger heal insid
  • LuaJit FFI 从 C 函数返回字符串到 Lua?

    假设我有这个 C 函数 declspec dllexport const char GetStr static char buff 32 Fill the buffer with some string here return buff 这
  • 如何更新lua中的时间以反映执行过程中系统时区的变化?

    Problem 我想修改awful widget textclockAwesome wm 中的小部件可以立即反映系统时区的更改 这个小部件和所有的 Awesome wm 配置都是用 lua 编写的 目前 如果系统时区发生更改 小部件将继续根
  • Lua:冒号符号、“自我”和函数定义与调用

    我对定义 调用 Lua 函数时使用的冒号表示法感到非常困惑 我以为我已经明白了 直到我看到这段代码 function string PatternSafe str return str gsub pattern escape replace
  • 循环直到在表中找到 2 个特定值?

    我试图找到一种更聪明的方法来解决这个问题 这是与游戏相关的代码的摘录 它循环遍历每个背包的每个插槽 直到找到铲子和绳子 local continue local foundShovel foundRope for i 0 Container
  • 如何解密Lua字节码?

    早上好 我正在尝试破译 Moon 字节码 但我无法以任何方式 有人可以帮助我吗 我有这个 例如 code 27 76 117 97 81 0 1 4 4 4 8 0 如何将此字节码解密为文本 我已经在这里搜索 http www asciit
  • 为什么 LuaJIT 和 Lua 中的数字舍入格式不同?

    Using string format 据说遵循 Csprintf 在 LuaJIT 轮次中格式化数字与我尝试过的所有其他 Lua 解释器不同 lua v Lua 5 4 1 Copyright C 1994 2020 Lua org PU
  • Lua中如何获取表中的最大整数?

    Lua中如何获取表中的最大整数 在Lua 5 1及更早版本中 你可以使用 math max unpack 1 2 3 4 5 这受到Lua堆栈大小的限制 在 PUC Lua 5 1 上 该值的最大值可达 ca 8000 个数字 如果堆栈空闲
  • 为什么 LuaJIT 这么好?

    编辑 不幸的是 LuaJIT 已从下面链接的比较中删除 This 比较 http shootout alioth debian org u64 which programming languages are fastest php编程语言的
  • Lua 从 5.1 更新 - LUA_GLOBALSINDEX 问题

    我最近将旧的 Lua 5 1 项目更新到了该库的最新版本 但遇到了问题LUA GLOBALSINDEX 它变得不确定 我只用过它lua getfield函数 像这样 void luastartgame void if startgamefu
  • VB6 - Lua 集成

    我想知道是否有人有任何集成 Lua 和 VB6 的技巧 我正在运行一个小型在线角色扮演游戏 添加一些脚本会很棒 嗯 这是可行的 我曾经为 Lua 5 0 2 做过 但找不到文件 在您拥有的选项中 您可以 将 Lua 封装在公开 Lua AP
  • Lua 将字符串转换为数字 - 取决于语言环境

    刚刚注意到字符串 and tonumber 在 Lua 中是依赖于语言环境的 知道如何在不使用的情况下将字符串转换为数字tonumber 谢谢 例如将字符串 58 5 转换为 58 5 另外 当我尝试将带点的数字传递给函数时 该函数会转换
  • 如何在我的 Lua 脚本中添加“睡眠”或“等待”?

    我正在尝试通过更改一天中的时间来为游戏制作一个简单的脚本 但我想快速完成 这就是我要说的 function disco hour minute setTime 1 0 SLEEP setTime 2 0 SLEEP setTime 3 0

随机推荐

  • [论文阅读] (14)英文论文实验评估(Evaluation)如何撰写及精句摘抄(上)——以入侵检测系统(IDS)为例

    娜璋带你读论文 系列主要是督促自己阅读优秀论文及听取学术讲座 并分享给大家 希望您喜欢 由于作者的英文水平和学术能力不高 需要不断提升 所以还请大家批评指正 非常欢迎大家给我留言评论 学术路上期待与您前行 加油 前一篇从个人角度介绍英文论文
  • Linux调出git页面,Linux 显示 git 分支 及 完整路径

    一 编辑 bashrc文件vim bashrc 二 在文件末尾添加如下shellfunction git branch branch git branch 2 gt dev null grep sed e s if branch then
  • 在线使用AI合集

    POE 前言 目前有关注的小伙伴应该会发现 ChatGPT注册功能已经关闭 那些还没有注册的小伙伴岂不是不能使用ChatGPT 今天为大家推荐的就是Poe AI机器人集合 Sage Claude ChatGPT Dragonfly Poe链
  • 前端数据请求的10种方式与最佳实践

    前言 在前端开发中 数据请求是经常遇到的一个问题 本文将介绍前端常见的10种数据请求方式 并给出每个方式的代码示例与使用场景 以帮助开发者更好的选择和使用 1 Fetch API Fetch API 是浏览器内置的一个用于网络请求的全局接口
  • 在ubuntu下安装并测试pig以及常见的问题

    1 安装 只安装在namenode节点上即可 1 1 下载并解压 下载 http pig apache org releases html下载pig 0 12 1版本的pig 0 12 1 tar gz 存放路径 home Hadoop 解
  • EXCEL导出封装 C#

    public class ExportToExcel public void Export List
  • flutter 一个Widget布局只return一次,但是可以有叠加覆盖的思想

    首先一个Widget只会return一次 但是如果有多个情况 多个判断 通过不同情况返回不同布局 就可以通过叠加的方式 下一个布局会替换掉上一个布局 messageTypeView Container 保底防止报错 文字 case 1 me
  • STM32串口通信详解

    作者简介 嵌入式入坑者 与大家一起加油 希望文章能够帮助各位 个人主页 rivencode的个人主页 系列专栏 玩转STM32 保持学习 保持热爱 认真分享 一起进步 目录 一 数据通信方式 1 串行与并行通信 2 全双工 半双工及单工通讯
  • 采用update-alternatives 切换python版本

    update alternatives是Debian提供的一个工具 非Debian系的就不用看了 原理类似于上面一个办法 也是通过链接的方式 但是其切换的过程非常方便 首先看一下update alternatives的帮助信息 update
  • [Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL s...

    Err 1064 You have an error in your SQL syntax check the manual that corresponds to your MySQL server version for the rig
  • kpca故障诊断matlab,关于用KPCA做故障检测,请教SPE控制图应该怎么做

    function qn kpca dtrain kernel q Fa Ca KPCA 核主成分分析 使用 trainFeat bj kpca data kernel p1 p2 输入 data 原始数据文件名 kernel 核函数 p1
  • eclipse导入外部项目后出现红叉解决方法

    eclipse开发工具中 在导入java项目时 有时会出现红叉 的现象 并且会发现里面的程序仍然能正常运行 原因 因为每个电脑上eclipse的环境都不太一样 导入项目后才回有红叉 这时只需要该变一下这个项目的环境就可以了 解决方法 第一步
  • nrm 切换 npm 源

    npm 配置仓库 查看当前仓库配置 npm config list 查看配置 npm config ls l 查看详细配置 可以看到 registry 配置 就是仓库地址 简述修改配置的 3 种方式 1 通过 config 配置 npm c
  • cesium for ue->CesiumUtility

    该模块共18个文件 3152行 含注释 截至2022年11月9日 剩下13个文件 1443行
  • 贝叶斯相关公式(Bayes)

    这里只是记录一下 非常推荐马同学高等数学 文末有原文 点击这里看里面的例一应该是理解贝叶斯公式最好的例子 如果你稍微有一些基础 我觉得文末第二个链接中的例一更加适合你 代数推导 1 贝叶斯公式 是根据条件概率推导的 P A B P AB P
  • 基于ssm+ajax实现的多条件带省略号分页

    ssm ajax layui实现的多条件分页源码 案列种包含数据库和前后台完整源码 演示地址 ssm ajax实现的多条件分页源码 前台核心代码 layui use form function var form layui form for
  • 一些论文审稿方面的体会

    本人小硕在读 老师也让帮忙审了论文 多是与自己领域相关的 老师让多学习学习 每次审论文都感觉诚惶诚恐 要是提的问题太多吧 感觉万一给拒了作者该多伤心啊 这挑的问题少吧 这明显对不起更多的人嘛 大体总结一下自己遇到的问题吧 一 现在论文提交量
  • Win10+CUDA8.0+Visual Studio2013安装、环境配置教程

    最近刚开始接触opencv的GPL编程 所以自己搜了下网上有关配置CUDA的过程 经过摸索整理 配置成功 现将教程整理如下 1 下载CUDA安装包 下载地址https developer nvidia com cuda downloads
  • 使用CUDA和CUFFT进行快速1D卷积的示例

    使用CUDA和CUFFT进行快速1D卷积的示例 在计算机视觉 数字信号处理和机器学习中 卷积是一种常见的操作 然而 卷积操作通常需要大量计算 因此需要一种高效的方法来完成 CUDA和CUFFT可以用于对使用FFT的快速1D卷积进行加速 在本
  • [Unity XLua]热更新XLua入门(一)-基础篇

    Aladdin XLua 前言 前段时间腾讯开源了一个内部热更框架XLua在Unity开发群里引起一阵热议 也受到广大开发者的热捧 然后我当然也抱着好奇的心去学习学习 后面也会将扩展之后的工程放在git上 大家一起学习交流 在此感谢XLua