【UE Lua】 快速入门(基础语法、与UE引擎的交互)

目录

  • [0 引言](#0 引言)
  • [1 基础语法](#1 基础语法)
    • [1.1 变量和数据类型](#1.1 变量和数据类型)
    • [1.2 注释](#1.2 注释)
    • [1.3 控制结构](#1.3 控制结构)
    • [1.4 函数](#1.4 函数)
    • [1.5 表(Table)](#1.5 表(Table))
    • [1.6 元表(Metatable)](#1.6 元表(Metatable))
    • [1.7 字符串操作](#1.7 字符串操作)
    • [1.8 模块和包](#1.8 模块和包)
    • [1.9 错误处理](#1.9 错误处理)
  • [2 数据结构 - 表](#2 数据结构 - 表)
    • [2.1 表(Table)](#2.1 表(Table))
    • [2.2 元表(Metatable)](#2.2 元表(Metatable))
    • [2.3 `__index` 元方法](#2.3 __index 元方法)
      • [2.3.1 `__index` 作为表](#2.3.1 __index 作为表)
      • [2.3.2 `__index` 作为函数](#2.3.2 __index 作为函数)
    • [2.4 表和元表的区别](#2.4 表和元表的区别)
  • [3 面向对象范式](#3 面向对象范式)
  • [4 Lua与UE引擎的交互](#4 Lua与UE引擎的交互)
    • [4.1 使用第三方插件 UnLua](#4.1 使用第三方插件 UnLua)
    • [4.2 使用 LuaBridge](#4.2 使用 LuaBridge)
    • [4.3 使用 Unreal Engine Lua Plugin](#4.3 使用 Unreal Engine Lua Plugin)
    • [4.4 底层实现原理](#4.4 底层实现原理)
      • [4.4.1 嵌入 Lua 解释器](#4.4.1 嵌入 Lua 解释器)
      • [4.4.2 绑定 C++ 和 Lua](#4.4.2 绑定 C++ 和 Lua)
      • [4.4.3 脚本加载和执行](#4.4.3 脚本加载和执行)
      • [4.4.4 事件和回调机制](#4.4.4 事件和回调机制)
      • [4.4.5 总结](#4.4.5 总结)
  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:UE虚幻引擎专栏
  • 💥 标题:【UE Lua】 快速入门
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!
  • 🎈 最后:文章作者技术和水平有限,如果文中出现错误,希望大家能指正,同时有问题的话,欢迎大家留言讨论。

0 引言

1 基础语法

Lua 是一种轻量级的脚本语言,语法简洁且易于学习。以下是 Lua 脚本的基础语法,包括变量、数据类型、控制结构、函数、表、元表等。

1.1 变量和数据类型

Lua 是动态类型语言,变量不需要声明类型。

lua 复制代码
-- 变量
local a = 10        -- 整数
local b = 3.14      -- 浮点数
local c = "Hello"   -- 字符串
local d = true      -- 布尔值
local e = nil       -- 空值

1.2 注释

Lua 支持单行注释和多行注释。

lua 复制代码
-- 单行注释

--[[
多行注释
可以跨越多行
]]

1.3 控制结构

条件语句

lua 复制代码
local x = 10

if x > 0 then
    print("x is positive")
elseif x < 0 then
    print("x is negative")
else
    print("x is zero")
end

循环语句

lua 复制代码
-- while 循环
local i = 1
while i <= 5 do
    print(i)
    i = i + 1
end

-- for 循环
for i = 1, 5 do
    print(i)
end

-- 泛型 for 循环
local t = {10, 20, 30}
for index, value in ipairs(t) do
    print(index, value)
end

1.4 函数

lua 复制代码
-- 定义函数
function add(a, b)
    return a + b
end

-- 调用函数
local result = add(3, 4)
print(result)  -- 输出 7

-- 匿名函数
local multiply = function(a, b)
    return a * b
end

print(multiply(3, 4))  -- 输出 12

1.5 表(Table)

表是 Lua 中唯一的数据结构,可以用来表示数组、字典、集合、对象等。

lua 复制代码
-- 创建一个空表
local t = {}

-- 数组
local array = {1, 2, 3, 4, 5}
print(array[1])  -- 输出 1

-- 字典
local dict = {name = "Alice", age = 30}
print(dict["name"])  -- 输出 "Alice"
print(dict.age)      -- 输出 30

-- 嵌套表
local nested = {a = {b = {c = 10}}}
print(nested.a.b.c)  -- 输出 10

1.6 元表(Metatable)

元表用于改变表的行为,可以定义一些特殊的操作,如算术运算、比较运算、表访问等。

lua 复制代码
-- 创建一个表
local myTable = {name = "Alice"}

-- 创建一个元表
local myMetatable = {
    __index = {age = 30}
}

-- 设置元表
setmetatable(myTable, myMetatable)

-- 访问表中的值
print(myTable.name)  -- 输出 "Alice"
print(myTable.age)   -- 输出 30  (从元表中获取)

1.7 字符串操作

Lua 提供了一些常用的字符串操作函数。

lua 复制代码
local str = "Hello, World!"

-- 获取字符串长度
print(#str)  -- 输出 13

-- 字符串连接
local str2 = str .. " Lua"
print(str2)  -- 输出 "Hello, World! Lua"

-- 字符串查找
local start, finish = string.find(str, "World")
print(start, finish)  -- 输出 8 12

-- 字符串替换
local newStr = string.gsub(str, "World", "Lua")
print(newStr)  -- 输出 "Hello, Lua!"

1.8 模块和包

Lua 支持模块和包,可以通过 require 函数加载模块。

lua 复制代码
-- mymodule.lua
local mymodule = {}

function mymodule.greet(name)
    print("Hello, " .. name)
end

return mymodule

-- main.lua
local mymodule = require("mymodule")
mymodule.greet("World")  -- 输出 "Hello, World"

1.9 错误处理

Lua 提供了 pcallxpcall 函数用于错误处理。

lua 复制代码
-- 使用 pcall 进行错误处理
local status, err = pcall(function()
    error("An error occurred")
end)

if not status then
    print("Error: " .. err)
end

2 数据结构 - 表

在 Lua 中,表(table)是最重要的数据结构,而元表(metatable)则是用于改变表行为的机制。以下是对表和元表的详细解释,以及 __index 元方法的作用。

2.1 表(Table)

表是 Lua 中唯一的数据结构,可以用来表示数组、字典、集合、对象等。表是动态的,可以根据需要添加或删除键值对。

lua 复制代码
-- 创建一个空表
local myTable = {}

-- 添加键值对
myTable["name"] = "Alice"
myTable["age"] = 30

-- 访问表中的值
print(myTable["name"])  -- 输出 "Alice"
print(myTable["age"])   -- 输出 30

2.2 元表(Metatable)

元表是一个特殊的表,可以用来改变另一个表的行为。通过设置元表,可以定义一些特殊的操作,如算术运算、比较运算、表访问等。

lua 复制代码
-- 创建一个表
local myTable = {}

-- 创建一个元表
local myMetatable = {}

-- 设置元表
setmetatable(myTable, myMetatable)

2.3 __index 元方法

__index 是元表中的一个特殊字段,用于处理对表中不存在的键的访问。当访问一个表中不存在的键时,Lua 会查找该表的元表中的 __index 元方法。如果 __index 是一个表,Lua 会在这个表中查找键;如果 __index 是一个函数,Lua 会调用这个函数。

2.3.1 __index 作为表

lua 复制代码
-- 创建一个表
local myTable = {name = "Alice"}

-- 创建一个元表
local myMetatable = {
    __index = {age = 30}
}

-- 设置元表
setmetatable(myTable, myMetatable)

-- 访问表中的值
print(myTable.name)  -- 输出 "Alice"
print(myTable.age)   -- 输出 30  (从元表中获取)

2.3.2 __index 作为函数

lua 复制代码
-- 创建一个表
local myTable = {name = "Alice"}

-- 创建一个元表
local myMetatable = {
    __index = function(table, key)
        if key == "age" then
            return 30
        else
            return nil
        end
    end
}

-- 设置元表
setmetatable(myTable, myMetatable)

-- 访问表中的值
print(myTable.name)  -- 输出 "Alice"
print(myTable.age)   -- 输出 30  (通过函数获取)

2.4 表和元表的区别

  1. 表(Table)

    • 表是 Lua 中的基本数据结构,用于存储键值对。
    • 表可以用来表示数组、字典、集合、对象等。
    • 表是动态的,可以根据需要添加或删除键值对。
  2. 元表(Metatable)

    • 元表是一个特殊的表,用于改变另一个表的行为。
    • 元表可以包含一些特殊的字段(如 __index__newindex__add 等),用于定义表的特殊操作。
    • 元表通过 setmetatable 函数设置,getmetatable 函数获取。
  • 表(Table) 是 Lua 中的基本数据结构,用于存储键值对。
  • 元表(Metatable) 是一个特殊的表,用于改变另一个表的行为。
  • __index 元方法用于处理对表中不存在的键的访问,可以是一个表或一个函数。

通过使用元表和 __index 元方法,可以实现更灵活和强大的表操作,满足各种编程需求。

3 面向对象范式

虽然 Lua 本身没有内置的面向对象编程支持,但可以通过元表(metatables)和表(tables)来实现面向对象编程。

lua 复制代码
-- 定义一个类
Person = {}
Person.__index = Person

-- 构造函数
function Person:new(name, age)
    local self = setmetatable({}, Person)
    self.name = name
    self.age = age
    return self
end

-- 方法
function Person:greet()
    print("Hello, my name is " .. self.name .. " and I am " .. self.age .. " years old.")
end

-- 创建对象
local person = Person:new("Alice", 30)
person:greet()

4 Lua与UE引擎的交互

Lua 与 Unreal Engine(UE)交互通常通过第三方插件或绑定库来实现。这些插件和库提供了在 UE 中嵌入 Lua 脚本的能力,使得开发者可以使用 Lua 编写游戏逻辑、控制游戏对象等。以下是一些常见的方法和工具:

4.1 使用第三方插件 UnLua

UnLua 是一个专门为 Unreal Engine 设计的 Lua 插件,提供了深度集成和高性能。以下是使用 UnLua 的基本步骤:

  1. 安装 UnLua

    • 下载并安装 UnLua 插件。
    • 将插件添加到你的 UE 项目中。
  2. 配置 UnLua

    • 在项目设置中启用 UnLua 插件。
    • 配置 Lua 脚本路径等参数。
  3. 编写 Lua 脚本

    • 创建 Lua 脚本文件,例如 MyScript.lua

    • 编写游戏逻辑,例如:

      lua 复制代码
      print("Hello from UnLua!")
      
      function OnBeginPlay()
          print("Game started")
      end
  4. 在 UE 中调用 Lua 脚本

    • 在 UE 蓝图或 C++ 代码中加载并执行 Lua 脚本。

      cpp 复制代码
      // 在 C++ 代码中加载 Lua 脚本
      UUnLuaManager* UnLuaManager = UUnLuaManager::Get();
      UnLuaManager->RunFile("MyScript.lua");
      
      // 调用 Lua 函数
      UnLuaManager->CallFunction("OnBeginPlay");

4.2 使用 LuaBridge

LuaBridge 是一个轻量级的 C++ 库,用于将 Lua 嵌入到 C++ 应用程序中。以下是使用 LuaBridge 与 UE 交互的基本步骤:

  1. 安装 LuaBridge

    • 下载并集成 LuaBridge 到你的 UE 项目中。
  2. 编写 C++ 代码

    • 在 UE 项目中编写 C++ 代码,加载并执行 Lua 脚本。

      cpp 复制代码
      #include "LuaBridge/LuaBridge.h"
      #include "lua.hpp"
      
      void RunLuaScript()
      {
          lua_State* L = luaL_newstate();
          luaL_openlibs(L);
      
          // 加载并执行 Lua 脚本
          if (luaL_dofile(L, "MyScript.lua") != LUA_OK)
          {
              const char* error = lua_tostring(L, -1);
              UE_LOG(LogTemp, Error, TEXT("Error: %s"), UTF8_TO_TCHAR(error));
          }
      
          // 调用 Lua 函数
          lua_getglobal(L, "OnBeginPlay");
          if (lua_pcall(L, 0, 0, 0) != LUA_OK)
          {
              const char* error = lua_tostring(L, -1);
              UE_LOG(LogTemp, Error, TEXT("Error: %s"), UTF8_TO_TCHAR(error));
          }
      
          lua_close(L);
      }

4.3 使用 Unreal Engine Lua Plugin

Unreal Engine Lua Plugin 是一个流行的插件,允许在 UE 中嵌入 Lua 脚本。以下是使用该插件的一些基本步骤:

  1. 安装插件

    • 下载并安装 Unreal Engine Lua Plugin。
    • 将插件添加到你的 UE 项目中。
  2. 配置插件

    • 在项目设置中启用 Lua 插件。
    • 配置 Lua 脚本路径等参数。
  3. 编写 Lua 脚本

    • 创建 Lua 脚本文件,例如 MyScript.lua

    • 编写游戏逻辑,例如:

      lua 复制代码
      print("Hello from Lua!")
      
      function OnBeginPlay()
          print("Game started")
      end
  4. 在 UE 中调用 Lua 脚本

    • 在 UE 蓝图或 C++ 代码中加载并执行 Lua 脚本。

      cpp 复制代码
      // 在 C++ 代码中加载 Lua 脚本
      ULuaState* LuaState = NewObject<ULuaState>();
      LuaState->DoFile("MyScript.lua");
      
      // 调用 Lua 函数
      LuaState->GetFunction("OnBeginPlay");
      LuaState->Call(0, 0);

4.4 底层实现原理

Lua 与 Unreal Engine(UE)交互的底层实现原理主要涉及以下几个方面:

  1. 嵌入 Lua 解释器

    • 在 UE 中嵌入 Lua 解释器,使得 Lua 脚本可以在 UE 的运行时环境中执行。
    • 这通常通过在 C++ 代码中包含 Lua 解释器库(如 lua.hpp)并初始化 Lua 解释器来实现。
  2. 绑定 C++ 和 Lua

    • 通过绑定机制,将 UE 的 C++ 类和函数暴露给 Lua,使得 Lua 脚本可以调用这些 C++ 函数。
    • 绑定机制可以手动实现,也可以使用自动化工具或库(如 LuaBridge、Sol2、UnLua 等)来简化绑定过程。
  3. 脚本加载和执行

    • 提供加载和执行 Lua 脚本的功能,使得 Lua 脚本可以在特定的事件或条件下执行。
    • 这通常通过在 C++ 代码中调用 Lua 解释器的 API 来实现,例如 luaL_dofile 用于加载和执行 Lua 脚本。
  4. 事件和回调机制

    • 实现事件和回调机制,使得 Lua 脚本可以响应 UE 中的事件(如游戏开始、对象碰撞等)。
    • 这通常通过在 C++ 代码中注册 Lua 函数作为回调函数,并在特定事件发生时调用这些回调函数来实现。

以下是一些具体的实现细节,展示了如何在 C++ 代码中嵌入 Lua 解释器并实现与 Lua 的交互。


4.4.1 嵌入 Lua 解释器

首先,需要在 C++ 代码中包含 Lua 解释器库并初始化 Lua 解释器:

cpp 复制代码
#include "lua.hpp"

lua_State* L = luaL_newstate();  // 创建一个新的 Lua 状态
luaL_openlibs(L);  // 打开 Lua 标准库

4.4.2 绑定 C++ 和 Lua

可以使用 LuaBridge 或其他绑定库来简化绑定过程。以下是使用 LuaBridge 的示例:

cpp 复制代码
#include "LuaBridge/LuaBridge.h"

void HelloWorld()
{
    UE_LOG(LogTemp, Log, TEXT("Hello from C++"));
}

void BindFunctions(lua_State* L)
{
    luabridge::getGlobalNamespace(L)
        .addFunction("HelloWorld", HelloWorld);
}

在 Lua 脚本中,可以调用绑定的 C++ 函数:

lua 复制代码
HelloWorld()  -- 调用 C++ 函数

4.4.3 脚本加载和执行

可以在 C++ 代码中加载和执行 Lua 脚本:

cpp 复制代码
if (luaL_dofile(L, "MyScript.lua") != LUA_OK)
{
    const char* error = lua_tostring(L, -1);
    UE_LOG(LogTemp, Error, TEXT("Error: %s"), UTF8_TO_TCHAR(error));
}

4.4.4 事件和回调机制

可以在 C++ 代码中注册 Lua 函数作为回调函数,并在特定事件发生时调用这些回调函数:

cpp 复制代码
// 注册 Lua 回调函数
lua_getglobal(L, "OnBeginPlay");
if (lua_isfunction(L, -1))
{
    lua_pcall(L, 0, 0, 0);
}

在 Lua 脚本中定义回调函数:

lua 复制代码
function OnBeginPlay()
    print("Game started")
end

4.4.5 总结

Lua 与 Unreal Engine 交互的底层实现原理主要涉及嵌入 Lua 解释器、绑定 C++ 和 Lua、加载和执行 Lua 脚本以及实现事件和回调机制。通过这些机制,可以在 UE 中嵌入 Lua 脚本,实现灵活的游戏逻辑编写和控制。使用第三方插件和库(如 UnLua、LuaBridge 等)可以简化这些过程,使得开发者更容易实现 Lua 与 UE 的交互。

相关推荐
编程武士1 分钟前
nginx openresty lua-resty-http 使用的一些问题记录
nginx·lua·openresty·lua-resty-http
程序员小羊!16 小时前
深入理解接口测试:实用指南与最佳实践5.0(三)
开发语言·lua
我码玄黄18 小时前
交互新体验:Axure动态面板下的图片拖动技巧
交互·产品经理·axure·交互设计
袁庭新1 天前
LuaRocks如何安装数据库驱动?
java·数据库·redis·lua·luarocks·袁庭新
qq_312920111 天前
安装lua-nginx-module实现WAF功能
nginx·junit·lua
单音GG1 天前
推荐一个基于协程的C++(lua)游戏服务器
服务器·c++·游戏·lua
袁庭新1 天前
安装luasocket模块时提示“sudo: luarocks:找不到命令“问题,该如何解决?
java·人工智能·ai·aigc·lua·luarocks·袁庭新
a48224252 天前
前端交互展示:裂缝与凹痕分割
前端·交互
PM大明同学2 天前
Axure PR 9 多级下拉选择器 设计&交互
交互·axure·photoshop
皮皮陶2 天前
Unity WebGL交互通信
unity·交互·webgl