【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 的交互。

相关推荐
mikey棒棒棒2 小时前
Redis——优惠券秒杀问题(分布式id、一人多单超卖、乐悲锁、CAS、分布式锁、Redisson)
数据库·redis·lua·redisson·watchdog·cas·并发锁
࿐ཉི༗࿆许七安༗࿆12 小时前
javaScript交互补充
前端·javascript·交互
Rhys..14 小时前
Jenkins上无法查看已成功生成的Junit报告
junit·sqlserver·jenkins
蕴微轩14 小时前
用openresty和lua实现壁纸投票功能
lua·openresty
Rhys..15 小时前
如何生成Junit报告
python·junit·jenkins
阿湯哥1 天前
Lua脚本核心语法介绍
开发语言·junit·lua
梓贤Vigo2 天前
【Axure高保真原型】拖动画图——画矩形案例
交互·产品经理·axure·原型
王小义笔记2 天前
Postman如何流畅使用DeepSeek
开发语言·测试工具·lua·postman·deepseek
梓贤Vigo2 天前
【Axure高保真原型】嵌套表格
交互·产品经理·axure·原型·中继器
PM大明同学2 天前
Axure PR 9 中继器 02 分页提示
ui·交互·产品经理·axure