问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Lua编程基础:从零开始掌握Unity和UE必备技能

创作时间:
作者:
@小白创作中心

Lua编程基础:从零开始掌握Unity和UE必备技能

引用
CSDN
12
来源
1.
https://blog.csdn.net/makyocute/article/details/131133159
2.
https://blog.csdn.net/dl15600383645/article/details/131629666
3.
https://blog.csdn.net/qq_34697930/article/details/136914495
4.
https://blog.csdn.net/lxl2092828212/article/details/137552670
5.
https://zhuanlan.zhihu.com/p/651637069
6.
https://blog.csdn.net/u013842501/article/details/107746657
7.
https://www.w3cschool.cn/lua/lua-basic-syntax.html
8.
http://www.cengage.com.cn/center/bookdetail/id/724
9.
https://doc.yonyoucloud.com/doc/wiki/project/lua/basic-syntax.html
10.
https://www.showapi.com/news/article/670111594ddd79f11a5b636e
11.
https://developer.aliyun.com/article/174178
12.
https://my.oschina.net/emacs_8885147/blog/17506962

Lua是一种轻量级的脚本语言,广泛应用于游戏开发领域。无论是Unity还是Unreal Engine(UE),Lua都能帮助你实现功能扩展和热更新。通过学习Lua的基本语法、控制结构、函数和表,你可以轻松上手这些主流游戏引擎。无论你是初学者还是有一定经验的开发者,掌握Lua都将为你的项目带来更多的可能性。快来一起探索Lua的世界吧!

01

Lua简介

Lua是一种轻量级的脚本语言,由巴西里约热内卢天主教大学的计算机科学系于1993年开发。它具有以下特点:

  1. 跨平台:Lua可以在多种操作系统上运行,包括Windows、Linux、macOS等。
  2. 易于嵌入:Lua可以很容易地嵌入到C/C++程序中,实现脚本语言与宿主程序的交互。
  3. 简洁:Lua的语法简洁明了,易于学习和使用。
  4. 高效:Lua的执行效率很高,适合用于游戏开发等性能敏感的场景。

Lua在游戏开发中的应用场景包括:

  1. 游戏逻辑编写:Lua可以作为一种脚本语言,用于游戏中的逻辑编写,例如定义游戏角色的行为、AI逻辑,处理游戏的战斗逻辑和流程控制等。
  2. 配置数据管理:Lua也可以作为一种配置语言,用于管理游戏数据,例如定义游戏中的各种参数、表格、配置表等。
  3. UI开发:Lua可以用于开发游戏界面,实现交互逻辑。
  4. AI控制:Lua可以用于实现游戏中的AI逻辑,包括路径寻找、状态机等。
02

Lua基本语法

Lua的学习曲线非常平缓,让我们从基础开始,逐步掌握这门语言的核心要素。

1. 交互式编程与脚本式编程

Lua支持两种编程模式:交互式编程和脚本式编程。

  • 交互式编程:通过命令行直接输入Lua代码并立即查看效果。你可以使用lua -ilua命令启动Lua交互环境。

    $ lua -i
    $ Lua 5.3.0  Copyright (C) 1994-2015 Lua.org, PUC-Rio
    > print("Hello World!")
    Hello World!
    >
    
  • 脚本式编程:将Lua代码保存到以.lua为后缀的文件中,然后通过Lua解释器执行。例如,将以下代码保存为hello.lua

    print("Hello World!")
    print("www.w3cschool.cn")
    

    使用lua命令执行脚本:

    $ lua hello.lua
    Hello World!
    www.w3cschool.cn
    

2. 注释

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

  • 单行注释:使用双减号--

    -- 这是一个单行注释
    
  • 多行注释:使用--[[ ... ]]包裹

    --[[ 
    这是一个
    多行注释
    ]]
    

3. 标示符

Lua的标示符用于定义变量、函数等用户自定义项。标示符必须以字母(A-Z或a-z)或下划线_开头,后面可以跟任意数量的字母、下划线或数字(0-9)。注意,Lua是区分大小写的语言。

4. 关键词

Lua有一系列保留关键字,不能用作变量名或函数名:

  • and, break, do, else, elseif, end, false, for, function, if, in, local, nil, not, or, repeat, return, then, true, until, while

5. 全局变量

在Lua中,变量默认是全局的。你不需要显式声明变量,直接赋值即可创建全局变量。访问未初始化的全局变量不会报错,而是返回nil

print(b)      --> nil
b = 10
print(b)      --> 10

要删除一个全局变量,可以将其赋值为nil

b = nil
print(b)      --> nil

6. 数据类型

Lua支持以下基本数据类型:

  • nil:表示空值或无值
  • boolean:布尔类型,值为truefalse
  • number:数值类型,支持整数和浮点数
  • string:字符串类型
  • table:表类型,Lua中唯一的复合数据类型
  • function:函数类型
  • userdata:用户数据类型,用于存储C语言中的数据结构
  • thread:协程类型

7. 运算符

Lua支持常见的算术、关系和逻辑运算符:

  • 算术运算符+(加)、-(减)、*(乘)、/(除)、%(取余)、^(幂)
  • 关系运算符==(等于)、~=(不等于)、<(小于)、>(大于)、<=(小于等于)、>=(大于等于)
  • 逻辑运算符and(与)、or(或)、not(非)

8. 控制结构

Lua提供了常见的控制结构,包括条件语句和循环语句:

  • if语句

    if condition then
        -- 代码块
    elseif condition then
        -- 代码块
    else
        -- 代码块
    end
    
  • while循环

    while condition do
        -- 代码块
    end
    
  • repeat循环

    repeat
        -- 代码块
    until condition
    
  • for循环

    for i = 1, 10 do
        -- 代码块
    end
    

9. 函数

Lua中的函数定义使用function关键字:

function myFunction(param1, param2)
    -- 函数体
    return result
end

函数可以有多个返回值:

function myFunction()
    return 1, 2, 3
end

local a, b, c = myFunction()
print(a, b, c)  --> 1 2 3

10. 表(Table)

表是Lua中唯一的复合数据类型,类似于其他语言中的数组或字典。表可以存储任意类型的值,并且可以用整数或字符串作为键。

  • 创建表

    local myTable = {}
    local myTable = {key1 = value1, key2 = value2}
    
  • 访问表元素

    local value = myTable["key"]
    local value = myTable.key
    
  • 表的常用操作

    table.insert(myTable, value)  -- 在表末尾插入元素
    table.remove(myTable, index)  -- 删除指定索引的元素
    
03

Lua在Unity中的应用

Lua在Unity中的主要作用包括游戏逻辑编写和配置数据管理。通过LuaInterface库,可以实现Lua与C#的互相调用。

1. Lua调用C#

在Lua中调用C#代码的示例:

using LuaInterface;

public class TestClass {
  public int TestMethod(int a, int b) {
    return a + b;
  }
}

public class LuaTest {
  LuaState lua; // Lua状态机
  LuaFunction func; // Lua函数

  void Start() {
    lua = new LuaState();
    lua.DoString("require('test')"); // 加载Lua脚本
    func = lua.GetFunction("testFunc"); // 获取Lua函数
    int result = func.Call(1, 2)[0].Int; // 调用Lua函数
    print(result);
  }
}

2. C#调用Lua

在C#中调用Lua代码的示例:

using LuaInterface;

public class LuaTest {
  LuaState lua; // Lua状态机

  void Start() {
    lua = new LuaState();
    lua.DoFile("test.lua"); // 加载Lua脚本
    lua.DoString("testFunc(1, 2)"); // 调用Lua函数
  }

  void Update() {
    lua.CheckFunction("update"); // 检查是否存在update函数
    lua.Push(this); // 将class实例压入栈中
    lua.Push(Time.deltaTime); // 将时间增量压入栈中
    lua.Call(2, 0); // 调用update函数,传入2个参数,取回0个返回值
  }
}

3. 使用场景区分

  • C#:主要用于游戏核心逻辑和性能敏感的模块,如游戏主循环、状态机、AI逻辑、射线检测、物理引擎等。
  • Lua:主要用于游戏可配置化、可扩展性和部分业务逻辑实现,如UI布局与逻辑、游戏属性配置、敌人行为定义、任务系统与对话逻辑、MOD与插件开发等。

4. 完整示例:Lua对象池

Lua脚本(object_pool.lua):

local objectPool = {}

-- 对象池中的对象
local objects = {}

-- 最大对象数量
local maxObjects = 10

-- 初始化对象池
function objectPool.init(max)
    maxObjects = max or maxObjects
end

-- 从对象池中获取一个对象
function objectPool.getObject()
    if #objects <= 0 then
        return nil
    else
        local obj = table.remove(objects)
        obj:SetActive(true)
        return obj
    end
end

-- 将一个对象放回对象池中
function objectPool.putObject(obj)
    obj:SetActive(false)
    if #objects >= maxObjects then
        GameObject.Destroy(obj)
    else
        table.insert(objects, obj)
    end
end

return objectPool

C#脚本:

using UnityEngine;
using LuaInterface;
using System.Collections;

public class ObjectPoolTest : MonoBehaviour {

    private LuaState lua;
    private LuaFunction getObjectFunc;
    private LuaFunction putObjectFunc;

    void Start() {
        lua = new LuaState();
        lua.DoFile("object_pool.lua");
        getObjectFunc = lua.GetFunction("getObject");
        putObjectFunc = lua.GetFunction("putObject");
    }

    void Update() {
        // 使用对象池获取对象
        GameObject obj = getObjectFunc.Call()[0].ObjectValue as GameObject;
        if (obj != null) {
            // 使用对象
            // ...
            // 将对象放回对象池
            putObjectFunc.Call(obj);
        }
    }
}
04

Lua在Unreal Engine中的应用

在Unreal Engine中使用Lua,主要通过UnLua插件实现。UnLua提供了蓝图绑定功能,可以在Lua中进行逻辑开发,并利用Lua的热更新特性,快速迭代开发表层逻辑。

1. UnLua环境搭建

  1. 下载UnLua插件包
  2. 将插件目录下的Plugin文件夹拷贝到UE项目根目录下
  3. 如果是蓝图工程,需要先在工程中新建C++类,再拷贝Plugin,否则无法编译
  4. 打开VS进行编译
  5. 编译时如果出现"error C4309: “static_cast”: 截断常量值"错误,需要在报错行将0xEF修改为0xEFu
  6. 编译成功后,打开UE编辑器

2. UnLua使用示例

创建一个控件蓝图UMG_Login,然后进行蓝图绑定:

  1. 点击UE编辑器上方菜单的UnLua,选择绑定,并编译蓝图
  2. 打开蓝图图表,左侧Interface处双击进入Get Module Name
  3. 在函数返回值中添加Lua文件的名称,命名规则为文件夹.文件名_C,例如UMG_Login_C
  4. 编译、保存
  5. 点击UnLua插件,创建Lua模板

Lua文件示例:

local M = {}

local PrintString = UE.UKismetSystemLibrary.PrintString

function M.Print(text, color, duration)
    color = color or UE.FLinearColor(1, 0, 1)
    duration = duration or 500
    PrintString(nil, text, true, false, color, duration)
end

return M

在关卡蓝图中加载UMG:

function M:ReceiveBeginPlay()
    local Widget = UE.UWidgetBlueprintLibrary.Create(self, UE.UClass.Load("/Game/UI/UMG_Login.UMG_Login_C"))
    if Widget then
        Widget:AddToViewport()
    end
end

注意:在UnLua的git仓库中提供的加载方式中,路径写法可能需要调整。例如,将官方的路径写法改为"/Game/UI/UMG_Login.UMG_Login_C"

05

Lua游戏开发最佳实践

Lua在游戏开发中的最佳实践包括:

  1. 脚本语言的使用:Lua作为脚本语言,可以实现游戏逻辑的快速迭代和热更新。
  2. Lua与C/C++的整合:通过LuaGlue函数实现Lua与C/C++的交互,可以将性能敏感的模块用C/C++实现,而将逻辑控制部分用Lua实现。
  3. 游戏数据处理:Lua适合处理游戏中的配置数据,如角色属性、物品信息等。
  4. GUI开发:Lua可以用于开发游戏界面,实现交互逻辑。
  5. 游戏编程:Lua可以实现游戏主循环、事件处理等核心逻辑。
  6. AI控制:Lua适合实现游戏中的AI逻辑,包括路径寻找、状态机等。

通过合理使用Lua,可以实现游戏开发的模块化和可维护性,同时提高开发效率。

06

总结与展望

Lua作为一门轻量级的脚本语言,在游戏开发领域展现出了强大的生命力。它不仅能够帮助开发者实现游戏逻辑的快速迭代,还能通过热更新机制,让游戏在不重启的情况下完成逻辑更新。Lua与C/C++的完美结合,使得它在保持高性能的同时,又能享受到脚本语言带来的便利。

随着游戏开发技术的不断发展,Lua在游戏开发中的应用场景将会越来越广泛。无论是独立游戏开发者,还是大型游戏工作室,Lua都将成为游戏开发中不可或缺的工具之一。掌握Lua编程技能,将为你的游戏开发之路开启新的篇章。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号