百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

unity3d开发教程-lua入门(unity 3d游戏开发(第2版))

liuian 2025-03-20 16:22 32 浏览

如果你还没有编程基础,建议你先学习一些编程基础。本文不是完全菜鸟教程,主要针对有其他语言经验的开发者,如果想看菜鸟教程,建议看菜鸟教程的 Lua教程。

先看一个简单类的代码

  1 ---@class BsnsPack @Base class of business pack
  2 local BsnsPack = {
  3     -- class fields
  4     maxSerialNo = 0,
  5 }
  6 
  7 BsnsPack.__index = BsnsPack
  8 
  9 --- new()
 10 ---@return BsnsPack
 11 function BsnsPack.new()
 12     local o = {}
 13 
 14     -- member fields
 15     o.serialNo = 0
 16     o.mod = 0
 17     o.cmd = 0
 18     o.payload = nil
 19     
 20     -- bind BsnsPack methods
 21     setmetatable(o, BsnsPack)
 22     return o
 23 end
 24 
 25 --- set serial No.
 26 ---@param serialNo number
 27 function BsnsPack:setSerialNo(serialNo)
 28     self.serialNo = serialNo
 29 end
 30 
 31 --- get serial No.
 32 ---@return number
 33 function BsnsPack:getSerialNo()
 34     return self.serialNo
 35 end
 36 
 37 --- set mod
 38 ---@param mod number
 39 function BsnsPack:setMod(mod)
 40     self.mod = mod
 41 end
 42 
 43 --- get mod
 44 ---@return number
 45 function BsnsPack:getMod()
 46     return self.mod
 47 end
 48 
 49 --- set cmd
 50 ---@param cmd number
 51 function BsnsPack:setCmd(cmd)
 52     self.cmd = cmd
 53 end
 54 
 55 --- get cmd
 56 ---@return number
 57 function BsnsPack:getCmd()
 58     return self.cmd
 59 end
 60 
 61 --- set payload
 62 ---@param payload any
 63 function BsnsPack:setPayload(payload)
 64     self.payload = payload
 65 end
 66 
 67 --- get payload
 68 ---@return any
 69 function BsnsPack:getPayload()
 70     return self.payload
 71 end
 72 
 73 function BsnsPack.test()
 74     print(BsnsPack.serialNo)
 75 end
 76 
 77 --- testPrivate
 78 ---@param self BsnsPack
 79 local function testPrivate(self)
 80     print(self.serialNo)
 81 end
 82 
 83 ---@alias Request BsnsPack @Request is BsnsPack
 84 local Request = BsnsPack
 85 
 86 ---@class Response : BsnsPack @Response class
 87 local Response = {}
 88 setmetatable(Response, BsnsPack) -- bind super methods
 89 Response.__index = Response
 90 
 91 --- new()
 92 ---@return Response
 93 function Response.new()
 94     local o = BsnsPack.new()
 95 
 96     -- member fields
 97     o.code = 0
 98 
 99     setmetatable(o, nil) -- remove original metatable
100     setmetatable(o, Response) -- bind Response methods
101     return o
102 end
103 
104 --- get result code
105 ---@return number
106 function Response:getCode()
107     return self.code
108 end
109 
110 local bsnsPack = {}
111 bsnsPack.BsnsPack = BsnsPack
112 bsnsPack.Request = Request
113 bsnsPack.Response = Response
114 
115 return bsnsPack

1、第1行:这是一行注释

Lua的行注释以两个减号 -- 开头,

class注解:---@class TYPE[: PARENT_TYPE {, PARENT_TYPE}] [@comment]

这样有利于 VS Code 代码提示,例如将鼠标放到代码中出现 BsnsPack 的地方上,会有小弹窗提示这个table的key,以及key的类型。

用得比较多的注解有 ---@class,---@return,---@param

2、第2行,定义一个叫 BsnsPack 的class(通过table模拟)。

Lua里没有类,Lua的结构化数据类型叫table,基于key-value结构。相对于其他语言的 map / dictionary。访问一个table的key对应的值,可以用点 . 来访问,也可以用中括号[]来访问

Lua里没有单独的数组结构,也是基于table,数组下标是key,数组元素是value,要注意的是,Lua里数组下标是从1开始的。

创建table的最简单方式就是花括号 {},创建一个空table。

Lua是脚本语言,变量不需要指定类型,只需要给它赋值。所以 BsnsPack = {maxSerialNo = 0,} 相当于定义了个变量 BsnsPack,它的值是一个table。

Lua的变量默认是全局的,加载到内存的Lua代码都可以访问这个变量。为了避免命名冲突和意外修改,一般建议变量定义为局部变量,限制它的作用域。在变量前面加个 local定义局部变量。

这里定义的 BsnsPack ,作用域只在这个文件里。其他文件不能访问。也可以在函数、代码块里用 local 定义局部变量。

3、第7行,给 BsnsPack一个叫 __index 的 key 赋值为 BsnsPack 自己

Lua 的 table 里,__index 是个特殊的key,这是 Lua实现类和继承的关键。

Lua里有个概念叫做元表。Lua定义了一些语言默认key,这些key一般跟 +、-、*、/等操作符、key的访问、值更新关联,这些key叫做元方法(Lua里的函数/方法也可以作为值),这些元方法合起来叫元表。

Lua里设置元表的方法是代码第 21 行的 function setmetatable(t, metatable),调用这个方法会让参数 metatable 成为 参数 t 的元表。

设置元表后,在代码里访问参数 t 的一个key时会发生以下情况:

1)Lua先在 t 里找,看有没有这个key,如果有,就返回这个key的值。否则,执行2)

2)Lua看参数 metatable 有没有 __index 这个key,如果有,就在 __index 对应的值里查找(__index的值如果是表,在这个表里查找;如果是函数,执行这个函数)

BsnsPack.__index = BsnsPack,如果其他的table设置 BsnsPack 为元表,就可以访问 BsnsPack 所有的key。 这些key的值如果是方法,就可以调用这些方法。

所以 BsnsPack 可以定义方法的模板,这就跟class类似。BsnsPack定义的数据key,相当于静态字段class field。BsnsPack定义的方法key,可以是成员方法member method,也可以是class method,后面介绍

4、第11~23行,定义BsnsPack的一个叫new的key,它的值是一个方法

Lua里一个代码块不用花括号{},通过end作为结束标记。

定义方法用 function 开头,用点.或者冒号:分割talbe名和方法名,

用冒号:定义的方法,会有个默认参数self,相当于调用者,如果外部用 BsnsPack:new() 这样调用,则self == BsnsPack,如果用a:new()这样调用,self==a。

用点.定义的方法,没有默认参数,只能显式写参数self。

一般地,用冒号:定义成员方法member method(例如第23行的 function BsnsPack:setSerialNo(serialNo) )

1)调用 o:setSerialNo(serialNo) 时,这里的self是对象o,只改对象o的serialNo,其他对象的serialNo不受影响。

用点.定义构造对象的方法(例如第11行的 function BsnsPack.new()),以及静态方法class method(例如第69行的 function BsnsPack.test() )

1)在其他地方通过 BsnsPack.new()构造BsnsPack对象

1)在其他地方通过 BsnsPack.test()调用类方法

建议,方法定义的时候是冒号:,调用的时候用冒号:,定义的时候是点.,调用的时候也用点.

构造方法不一定叫new,只是为了统一,建议都用new,与其他语言一致。

方法new里面的 local o = {},定义的key都是成员字段member field(每次调用方法 BsnsPack.new() 都创建一个新的 table并对其字段初始化后返回)

Lua没有私有的成员方法,可以定义文件的 local 方法,把对象作为参数self显式的传进去(例如第79行 local function testPrivate(self))

5、第84行,给类BsnsPack定义一个别名 Request,其实就是把一个table赋值给另外一个变量

6、第87~102行,定义一个类Response,继承基类BsnsPack

第87行,定义子类Response

第88行,设置元表,使得Response可以访问BsnsPack所有的key(继承BsnsPack所有的方法)

第89行,所有对象可以访问Response所有的key(通过递归,包括BsnsPack所有的key)

第94行,通过调用BsnsPack构造方法初始化o,o是BsnsPack的对象,拥有基类所有的member field

第97行,定义Response相对于基类新增的字段code

第99、100行,修改o的元表为Response,这样o可以访问Response所有的成员方法 member method(通过递归,包括BsnsPack所有的成员方法)

Response可以重写BsnsPack的方法

1 function Response:getPayload()
2     return self.payload
3 end

由于Lua里访问key,先在table本身查找,如果没有才在元表查找,所以会调用重写的方法,实现多态。

7、第110~115行,导出本文件定义的类。

由于class的定义都是以 local 方式定义的局部变量,外部不能访问,所以要把它当作文件的返回值 return

如果该文件只导出一个class,直接return这个局部变量就可以,(例如,如果只导出BsnsPack,return BsnsPack 就可以)

由于本文件需要导出3个class,这里把他们放到一个table里导出

其他文件需要访问这个文件的class,需要调用require方法导入进来,该方法的参数是路径(不含后缀.lua),返回值是这个lua文件的return值

1 local bsnsPack = require("Assets.Lua.bsns.bsns_pack")
2 local Request = bsnsPack.Request
3 local Response = bsnsPack.Response

8、如果想模块化管理,把一个模块所有的类通过一个文件暴露给其他模块,可以在这个文件定义一个局部变量,把这个模块所有的文件的类,都通过require导入进来,并赋值给跟类同名的key,最后返回这个局部变量

文件bsns.lua

 1 local bsns = {}
 2 
 3 local bsnsPack = require("Assets.Lua.bsns.bsns_pack")
 4 bsns.Request = bsnsPack.Request
 5 bsns.Response = bsnsPack.Response
 6 
 7 bsns.BsnsMod = require("Assets.Lua.bsns.bsns_mod")
 8 bsns.BsnsCenter = require("Assets.Lua.bsns.bsns_center")
 9 
10 return bsns

9、可以实现一个通用的类定义函数

 1 --- define a class
 2 --- t._className, a string array, define class name
 3 --- t._super, a table, define super class
 4 --- t.__ctor, a function(self, ...), define member fields
 5 --- @param t any
 6 function class(t)
 7     -- extends super
 8     if t._super ~= nil then
 9         -- static fields and methods
10         local superStaticClone = {}
11         for k, v in pairs(t._super) do
12             if k == "_ctor" then
13                 goto continue
14             end
15 
16             superStaticClone[k] = v
17 
18             ::continue::
19         end
20 
21         setmetatable(t, superStaticClone)
22     end
23     
24     t.__index = t
25     -- new method
26     t.new = function(...)
27         local o = {}
28         invokeCtor(o, t, ...)
29 
30         setmetatable(o, t) -- bind class
31         return o
32     end
33 
34     function invokeCtor(o, cls, ...)
35         if cls._super ~= nil then
36             invokeCtor(o, cls._super, ...)
37         end
38 
39         if cls._ctor ~= nil then
40             setmetatable(o, cls)
41             o:_ctor(...)
42             setmetatable(o, nil)
43         end
44     end
45 
46     return t
47 end

有了这个函数可以这样定义类

 1 local TestClass = class({
 2     -- class name
 3     _className = "TestClass",
 4 
 5     -- static fields:
 6     size = 2,
 7     count = 0,
 8 
 9     -- member:
10     _ctor = function(self, ...)
11         local params = {...}
12         self.count = params[1]
13         self.age = params[2]
14     end
15 })
16 
17 local TestClass2 = class({
18     _className = "TestClass2",
19     ---@class TestClass
20     _super = TestClass,
21 
22     _ctor = function(self, ...)
23         self.fdsl = 3256
24     end
25 })

10、简单语法介绍

1)Lua里的语句不需要分号;结尾

2)Lua常用的基本数据类型有nil、boolean、number、string、function、table

3)获取数组长度用 #数组变量,例如

1 local array = {"Lua", "Tutorial"}
2 local len = #array
3 print(len)

4)遍历数组用

1 for i, v in ipairs(table) do
2 
3 end

5)遍历对象用

1 for k, v in pairs(obj) do
2 
3 end

6)其他语法请查阅菜鸟教程

11、Lua代码规范可参考
https://lua.ren/topic/172/

相关推荐

联想小新怎么找售后维修(联想小新怎么找售后维修点)

给大家介绍几种解决的办法,大家可以试试:方法一:最简单的方法就是重启一下你的电脑,一般没有太大问题重启一下电脑就可以了。方法二:如果你电脑中安装了360安全卫士,那么你可以打开360安全卫士,然后点击...

笔记本win10系统重装(笔记本win10系统重装u盘启动)

win10系统重装方法如下第一步:下载安装好老毛桃U盘启动盘制作工具,制作一个U盘启动盘,建议U盘内存在8G以打开浏览器,搜索“老毛桃官网”,进入官网后,在首页点击“完整版”下载第二步:下载好win1...

主题之家移动版(主题中心下载手机版)

根据我的了解,汽车之家王国分为多个主题。其中包括新车评测、汽车导购、行业资讯、改装技术、赛车运动等。新车评测主题提供各种品牌和型号的汽车评测文章和视频,帮助消费者了解车辆性能和特点。汽车导购主题提供购...

win7电脑分盘(windows7电脑分盘)

在Win7系统电脑上分盘,您可以按照以下步骤进行操作:1.打开“计算机管理”:右键点击“计算机”图标,选择“管理”选项,打开“计算机管理”窗口。2.打开“磁盘管理”:在“计算机管理”窗口中,选择“...

电脑任务栏怎么还原到下边快捷键

电脑任务栏还原到下边方法:1.在任务栏上单击右键进入Windows电脑桌面后直接在任务栏上单击鼠标右键。2.点击锁定任务栏在弹出的菜单里面点击倒数第二个锁定任务栏选项。3.将任务栏拖到下方再按下鼠标左...

windows7怎么单击修复计算机

方法/步骤windows7的设置一般都可以在“控制面板”调整,鼠标的功能调整也不例外。首先打开“开始”-“控制面板”。“控制面板”默认是按照类别分类的,可能看不到鼠标选项,不过我们可以在搜索框里搜索“...

rog售后维修服务中心(rog官方维修点查询)

如果你的rog手机坏了,可以选择去rog手机官方维修点或者授权的维修中心修理。在这些地方,工程师们具有专业的维修知识和技能,能够确保对rog手机进行正确的维修和保养。此外,他们也会使用原厂备件,以确保...

装机系统哪个好(装系统那个好)

一、【重装win10正版系统】   二、【好用一键重装系统】  三、【优盘一键重装系统】 四、【免u盘一键重装系统】五、【小白在线一键重装系...

计算机怎么设置密码(计算机怎么设置密码锁屏)
  • 计算机怎么设置密码(计算机怎么设置密码锁屏)
  • 计算机怎么设置密码(计算机怎么设置密码锁屏)
  • 计算机怎么设置密码(计算机怎么设置密码锁屏)
  • 计算机怎么设置密码(计算机怎么设置密码锁屏)
win10刻录光盘的方法和步骤(win10系统怎么刻录光盘)

1.打开Windows10中的“文件资源管理器”,找到要刻录的文件或文件夹。2.选中文件/文件夹,右键单击选中“发送到-->DVDRW驱动器”。3.确认要刻录的光盘的名称和格式(默...

惠普笔记本电脑官网驱动下载

HP惠普打印机驱动官网是存在的。因为HP惠普是一家著名的电脑及相关产品制造商,他们会提供各种驱动程序和软件以保证设备的兼容性和稳定性。HP惠普打印机驱动官网可以通过搜索引擎查找,也可以通过HP惠普的官...

2025win7专业版激活密钥(2020win7专业版永久激活码)

cad序列号和密钥是111-111111,可以通用的,但激活码则需要通过CAD2014注册机对申请号的换算才能得出结果,当然结果有很多,用户可以不断的Generate一个。cad序列号和密钥是111-...

window7下载itunes什么版本(window7怎么下载itunes)

出现此问题一般是因为itunes没有正确安装,可以参考如下解决方法:1.请查看本机电脑数位,计算机---右键---属性---看是32的还是64的;2.官网下载数位对应的iTunes;3...

u盘什么牌子的好(大容量的u盘什么牌子好)

十大耐用云U盘排行分别是:第一名闪迪第二名雷克沙第三名金士顿第四名三星第五名美商海盗船第六名东芝第七名惠普第八名威刚第九名台电第十名朗科。十大耐用云U盘排行分别是:第一名闪迪第二名雷克沙第三名金士顿第...

英文翻译器下载(英文翻译器软件下载)

APK(全称:Androidapplicationpackage,Android应用程序包)是Android操作系统使用的一种应用程序包文件格式,用于分发和安装移动应用及中间件。一个Android...