教程-【唐老师】Unity热更新之Lua语法

环境搭建以及helloworld

  • LuaForWindows

  • IDE:VSCode、IDEA、LuaStudio……

第一个程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--单行注释
--lua可以省略分号
print("Hello World!")
--[[
多行
注释
]]

--[[
第二种
多行
注释
]]--

--[[
第三种
多行
注释
--]]

变量

  • 简单变量类型:

空 nil、 数值 number、字符串 string、布尔 boolean

  • 复杂变量类型:

函数 function

表 table

数据结构 userdata

协同程序 thread(线程)


lua中所有的变量都不需要声明变量类型,类型C#的var

lua中的变量可以随便赋值,自动识别类型//我理解为弱类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--nil
a = nil
print(a)

--number
a = 1.2
print(a)

--string
a = "helloworld"
print(a)

--boolean
a = false
print(false)

通过type可以获得变量类型

1
2
a = nil
print(type(a))

type函数也有返回值,是string类型的

1
2
print(type(type(a)))
--string

使用没有声明过的变量,不会报错,默认值为空

1
2
print(b)
--nil

字符串操作

1
2
3
--字符串操作
a = "双引号字符串"
b = '单引号字符串'

取字符串长度,中文在lua中占3个长度

1
2
3
4
5
6
s = "aBcDeF"
print(#s)
--6
s = "aBcDeF字符串"
print(#s)
--15

字符串多行打印

1
2
3
4
5
6
7
print("123\n123")

s = [[123
123
123
]]
print(s)

字符串拼接

1
2
3
4
5
6
7
print("123".."456")

s1 = "123"
s2 = 456
--也可以拼接数值
print(s1..s2)
--123456

占位符

1
2
3
4
5
6
7
8
print(string.format("我叫紫地丁,我%d岁了"3))
--我叫紫地丁,我3岁了

--[[
%d :数字
%s :字符
%a :与任何字符拼接
]]

其他类型转换到string

1
2
a = true
print(tostring(a))

字符串提供的公共方法

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
str = "aBcDeF"
print(string.upper(str))
--ABCDEF

print(string.lower(str))
--abcdef

大部分字符串操作不会改变原字符串
print(str)
--aBcDeF

--翻转字符串
print(string.reverse(str))
--FeDcBa

--字符串索引查找
print(string.find(str,"cDe"))
--3 5

--字符串截取
print(string.sub(str,3,4))

--字符串重复
print(string.rep(str,2))

--字符串修改
print(string.gsub(str,"cD","**"))

--字符转ASCII码
a = print(string.byte("Lua"),1)
--76

--ASCII转字符
print(string.char(a))
--L

运算符

算数运算符

还是那么些个+-*/%,但没有++,–,也没有复合运算符+=,-=等

还有C#没有的幂运算符^


string可以进行算数操作,会自动转成number

1
2
print("123"+1)
--124

条件运算符

还是那么些个>,<,==,>=,<=

以及有点不一样的不等于~=,即不等于

1
2
print(3~=1)
--true

逻辑运算符

与and,或or ,非not

1
2
print(not true)
--false

Lua支持逻辑运算的短路规则

1
2
3
4
5
print(false and print("123"))
--false
print(true and print("123"))
--123
--nil
  • Lua不支持位运算、三目运算

条件分支语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = 9
if a>5 then
print("啊对对对")
else
print("不对不对不对")
end

--多分支
if a<5 then
print("1234")
elseif a ==5 then
print("555")
else
print ("67890")
end

循环语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
--while循环
num = 0
while num<5 do
num = num+1
print(num)
end

--repeat循环
repeat
num=num-1
print(num)
until num<0

--for语句
for i=1,5 do
print(i)
end
--其中i会自动+1

--自定义i的增量
for i = 5,1,-1 do
print(i)
end

函数

无参数无返回

1
2
3
4
5
6
7
8
9
10
11
12
13
function f1()
print("f1")
end

--有点类似委托的写法
f2 = function()
print("f2")
end

f1()
--f1
f2()
--f2
  • lua中不能在函数声明前执行函数

有参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function f3(a)
print(a)
end

--Lua有很强的灵活性
f3(2)
--2
f3("123")
--123
f3(true)
--true
f3()
--nil
f3(1,2,3)
--1

有返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function f4(a)
return a
end

function f5(a)
return a,"456",true
end

print(f4("123"))
--123

print(f5("123"))
--123 456 true

a,b,c = f5("123")
print(a)
print(b)
print(c)
--[[
123
456
true
]]

函数是一个变量类型

1
2
print(type(f5))
--function

函数重载

  • Lua中不支持函数重载,默认调用最后一个声明的函数

变长参数

需要先用一个表将变长参数存起来,再使用变长参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function f6(...)
arg = {...}
for i =1,#arg do
print(arg[i])
end
end

f6(1,2,true,"4",5)
--[[
1
2
true
4
5
]]

函数嵌套

1
2
3
4
5
6
7
8
9
10
function f7()
f8 = function()
print(123)
end
return f8
end

f88 = f7()
f88()
--123

Lua中闭包的体现:通过函数嵌套改变参数的生命周期

1
2
3
4
5
6
7
8
9
function f9(x)
return function(y)
return x+y
end
end

f10 = f9(10)
print(f10(20))
--30

闭包函数:声明在一个函数中的函数,叫做闭包函数。

闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

闭包的特点:

让外部访问函数内部变量成为可能;

局部变量会常驻在内存中;

可以避免使用全局变量,防止全局变量污染;

会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

table实现数组

数组

声明数组

1
a = {1,2,"3",true,5,nil}

取用数组元素

1
2
3
4
5
print(a[0])
--nil
--Lua中索引从1开始
print(a[1])
--1

获取数组长度

1
2
3
4
5
6
7
8
9
print(#a)
--5
--在打印长度的时候,nil被忽略了

b = {1,1nil1,1}
print(#b)
--5
--唐老师说如果数组中有nil,nil会截断数组,也就是说刚才的输出应该得到2
--但我使用VSCode+Lua插件测试,只有nil在数组结尾的时候会忽略最后一个nil元素

遍历数组

1
2
3
4
for i = 1, #a do 
print(a[i])
end
--获取数组长度的例子说明,如此遍历数组不可靠

二维数组

1
2
3
4
5
a = {{1,2,3},{4,5,6}}
print(a[1][1])
--1
print(a[2][2])
--5

遍历

1
2
3
4
5
6
for i =1,#a do
b = a[i]
for j = 1,#b do
print(b[j])
end
end

自定义索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
aa = {[0] = 1,2,3,[-1]=4,5}
print(aa[0])
--1

print(#aa)
--3
--获取长度依然从1开始

--Lua底层代码造成的坑
aa = {[1]=1,[2]=2,[4]=4,[5]=5}
print(#aa)
--5

aa = {[1]=1,[2]=2,[5]=5}
print(#aa)
--2

迭代器遍历

迭代器遍历,主要是用来遍历表的

用#得到表的长度可能不准确,所以常用迭代器遍历表

ipairs

1
2
3
4
5
6
7
8
9
10
11
12
13
a = {[0]=1,2,[-1]=3,4,5}

--ipairs
--只能找到连续索引的值,如果中间断序了,也无法遍历后面的内容
--ipairs依然是从1开始遍历的
for i,k in ipairs(a) do
print(i..k)
end
--[[
12
24
35
]]

pairs

1
2
3
4
5
6
7
8
9
10
11
--pairs的功能相对强大
for i,v in pairs(a) do
print(i..v)
end
--[[
12
24
35
01
-13
]]

table实现字典

字典的声明和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a = {["name"]="紫地丁",["age"]=3,["1"]=1}

print(a[name])
--紫地丁
print(a.age)
---3

--print(a.1)
--不能用.数字的形式取值

a["sex"] = false
print(a.sex)
--false

a.age = 4;
print(a.age)
--4

--Lua中的字典不太存在删除的概念,只可能把值赋值为nil

字典的遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for k,v in pairs(a) do 
print(k,v)
end
--[[
name 紫地丁
sex true
age 4
]]

for k in pairs(a) do
print(k)
print(a[k])
end

for _,v in paris(a) do
print(v)
end
--类似C#的弃元,在这里更像是约定俗成的规范

table实现类

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
50
51
Student = {
age = 3,
name = "紫地丁",

Up = function()
print("我成长了")
end,

Learn = function(t)
print(t.name)
print("好好学习,天天向上")
end
}
--C#中使用类需要实例化,但Lua中没有面向对象的概念,这个Student本身是一个对象,而不是一个类,或者说是一个类有很多静态成员

Student.Up()
--我成长了
Student.sex = false
print(Student.sex)
--false

function Student.Speak()
print("说话")
end
Student.Speak()
--说话

print(age)
--nil
--LUa中依然有全局变量和局部变量的概念

Student.Learn(Student)
--[[
紫地丁
好好学习,天天向上
]]

--lua中点和冒号的区别:
Student:Learn()
--[[
紫地丁
好好学习,天天向上
]]
--冒号默认把自己作为第一个参数传入函数

--self关键字表示传入的第一个参数
function Student:Speak2()
print(self.name.."说话")
end
Student:Speak2()
--紫地丁说话

table的公共操作

1
2
t1 = {{age=1,name = "123"},{age = 2,name = "345"}}
t2 = {name = "紫地丁",sex = true}

插入

1
2
3
4
5
6
7
print(#t1)
--2
table.insert(t1,t2)
print(#t1)
--3
print(t1[3].sex)
--true

删除指定元素

1
2
3
4
5
6
7
8
9
10
11
12
--remove默认会移除最后一个索引的内容
table.remove(t1)
print(#t1)
--2
print(t1[1].name)
--123
print(t1[3])
--nil

--删除指定元素
table.remove(t1,1)
print(t1[1].name)

排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
t2= {5,2,7,9,5}
table.sort(t2)
for _,v in pairs(t2) do
print(v)
end
--[[
2
5
5
7
9
]]

--降序排列
table.sort(t2,function(a,b)
if a>b then return true
end
end)

for _,v in pairs(t2) do
print(v)
end

拼接

1
2
3
4
tb = {"123","456","789"}
a = table.concat(tb,";")
print(a)
--123;456;789

多Lua脚本的执行

全局变量和本地变量

我们之前所声明的变量大多是全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
a = 1
b = "2"

for i = 1,2 do
c = 3
end

print(c)
--3

fun = function()
tt = "123"
end
print(tt)
--nil
fun()
print(tt)
--123

用local关键字声明局部变量

1
2
3
4
5
6
7
8
9
for i = 1,2 do
local d = "3"
end
print(d)
--nil

local tt2 = "555"
print(tt2)
--555

多脚本执行

使用require关键字实现多脚本执行

test1.lua

1
2
3
4
--test1.lua
testA = "123"
local testB = "456"
print("test1")

test2.lua

1
2
3
4
5
6
7
8
--test2.lua
--先执行一遍test1.lua
require("test1")
print(testA)
--test1
--123
print(testB)
--nil

require也可以接收一个脚本的返回值

1
2
3
--test3.lua
print("test3")
return 123;
1
2
3
4
--test1.lua
a = require("test3")
print(a)
--123

脚本的卸载

再次使用require

1
require("test1")

test1不会再执行

也就是说,执行过的脚本不会再执行

通过package.loaded[]判断脚本是否执行过

1
2
print(package.loaded["test1"])
--true

也可以通过package.loaded卸载脚本

1
2
3
package.loaded["test1"] = nil
print(package.loaded["test1"])
--nil

但是全局变量testA还在,唐老师没有讲这件事

1
2
print(testA)
--123

大G表

xxxxxxxxxx4 1local testFun2 = xlua.get_generic_method(CS.Lesson12,”TestFun2”)2local testFun2_R = testFun2(CS.System.Int32)3–第一个参数传调用函数的对象,静态方法不用传4testFun2_R(obj,1)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
for k,v in pairs(_G) do
print(k,v)
end
--[[
pcall function: 0000000065b9ca70
getmetatable function: 0000000065b9d8a0
debug table: 0000000000709580
fun function: 000000000070d090
xpcall function: 0000000065b9c970
collectgarbage function: 0000000065b9d330
select function: 0000000065b9cb20
loadfile function: 0000000065b9d830
ipairs function: 0000000065b9d0e0
load function: 0000000065b9d730
assert function: 0000000065b9d980
table table: 0000000000708230
rawlen function: 0000000065b9cea0
warn function: 0000000065b9cf50
rawset function: 0000000065b9cdf0
os table: 0000000000709700
utf8 table: 0000000000709880
type function: 0000000065b9ca10
string table: 0000000000709b80
tt 123
print function: 0000000065b9cff0
c 3
b 2
a 1
rawequal function: 0000000065b9cf00
arg table: 0000000000709740
rawget function: 0000000065b9ce50
next function: 0000000065b9d130
testA 123
math table: 0000000000709500
dofile function: 0000000065b9d900
coroutine table: 0000000000709220
io table: 0000000000709a40
setmetatable function: 0000000065b9d560
tostring function: 0000000065b9caf0
pairs function: 0000000065b9d610
_G table: 0000000000706d70
_VERSION Lua 5.4
require function: 0000000000708de0
package table: 0000000000708e60
error function: 0000000065b9d2b0
tonumber function: 0000000065b9cbc0
]]

加了local的变量,也就是本地变量不会存到大G表中

可以在大G表中存储键值对

1
2
3
4
5
6
_G["a"] = 1
_G.b = 123
print(a)
--1
print(b)
--123

特殊用法

多变量赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
a,b,c = 1,2
print(a)
--1
print(b)
--2
print(c)
--nil

a,b = 3,4,5
print(a)
--3
print(b)
--4

多返回值

1
2
3
4
function Test()
return 10,20,30,40
end
a,b,c = Test()

逻辑与或

and和or不仅可以连接boolean,任何东西都可以用来连接

在lua中,只有nil和false才认为是假

在不同变量的连接中,依然遵守短路规则

1
2
3
4
5
6
7
8
print(4 and 2)
--2
print(nil and 1)
--nil
print(true or 1)
--true
print(false or 2)
--2

可以用这种性质模拟三目运算

1
2
3
4
x = 1
y = 2
biger = (x>y) and x or y
print(biger)

协同程序

协程的创建

1
2
3
4
5
6
7
8
9
10
11
12
fun = function()
print(123)
end

co = coroutine.create(fun)
--协程的本质是一个线程对象
print(type(co))
--thread

co2 = coroutine.wrap(fun)
print(type(co2))
--function

协程的运行

协程的创建方式不同,运行方式就不同

1
2
3
4
5
coroutine.resume(co)
--123

co2()
--123

协程的挂起

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
fun2 = function()
local i =1
while true do
print(i)
i = i+1
--协程的挂起函数
coroutine.yield(i)
end
end

co3 = coroutine.create(fun2)
coroutine.resume(co3)
coroutine.resume(co3)
--1
--2

--协程有返回值,第一个返回值表示协程是否执行成功,从第二个开始返回yield中的数据
isok,temp = coroutine.resume(co3)
--3
print(isok,temp)
--true 3

--wrap创建的协程也有返回值,但没有第一个默认返回值
co4 = coroutine.wrap(fun2)
temp = co4()
--1
print(temp)
--1
temp = co4()
--2
print(temp)
--2

协程的状态

协程有三种状态:dead、suspended、running

1
2
3
4
5
6
7
8
9
10
print(coroutine.status(co3))
--suspended
print(co)
--dead

co4 = coroutine.create(function()
print(coroutine.status(co4))
end)
coroutine.resume(co4)
--running

可通过coroutine.running得到正在运行的线程号

1
2
3
4
5
6
co5 = coroutine.create(function()
print(coroutine.running())
end)
coroutine.resume(co5)
--thread: 000000000066e4b8 false
--唐老师的教程中协程没有打印最后的这个false

元表

元表概念

任何表变量都可以作为另一个表变量的元表,任何表变量都可以有自己的元表(爸爸)

当我们在有元表的表中进行一些操作时,会执行元表的内容

设置元表

1
2
3
4
5
meta = {}
myTable = {}

setmetatable(myTable,meta)
--第一个参数是子表,第二个参数是元表

特定操作-tostring

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
meta2 = {
__tostring = function()
return "我是中国人"
end
}
print(meta2)
--table: 00000000006e9b20
myTable2 = {}
setmetatable(myTable2,meta2)
print(myTable2)
--我是中国人
--当子表要被当作字符串使用时,会默认调用它的元表中的__tostring方法(两个下划线)

--tostring方法也可以有参数
meta3 = {
__tostring = function(t)
return t.name.."是中国人"
end,
__call = function(a)
print(a)
print(",紫地丁今年3岁了")
end
}
myTable3 = {
name = "紫地丁"
}
setmetatable(myTable3,meta3)
print(myTable3)
--紫地丁是中国人

特定操作-call

1
2
3
4
5
6
7
--当子表被当作函数使用时,会调用元表中的__call方法
myTable3()
--[[
紫地丁是中国人
,紫地丁今年3岁了
]]
--call方法中的a参数默认当做myTable3自己

特定操作-运算符重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
meta4 = {
__add = function(t1,t2)
return t1.age+t2.age
end
}
myTable4 = {age = 1}
setmetatable(myTable4,meta4)
myTable5 = {age = 2}
print(myTable+myTable)
--3

其他运算符的关键字:
+ add
- sub
* mul
/ div
% mod
^ pow
== eq
< lt
<= le
.. concat

如果要用条件运算符比较两个对象,这两个对象的元表要一致才能准确调用方法

特定操作-index和newIndex

当子表中找不到某一个属性时,会到元表中index指定的表去找索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
meta5 = {}
--建议把index写在元表外部
meta5.__index = {age = 1}--index指向的表也可以是元表自己
myTable5 = {}
setmetatable(myTable5,meta5)

--当字表中找不到某一个属性时,会到元表中index指定的表去找索引
print(myTable5.age)
--1

--index可以多层套用
meta6father= {}
meta6father.__index = {age = 2}
meta6 = {}
meta6.__index = meta6
myTable6 = {}
setmetatable(myTable6,meta6)
setmetatable(meta6,meta6father)
print(myTable6.age)
--2

可以用rewget方法取消index的作用,找表自己的变量

1
2
print(rawget(myTable6),"age")
--nil

当赋值时,如果赋值一个不存在的索引,那么会把这个值赋值到newindex所指的表中,不会修改自己

1
2
3
4
5
6
7
8
9
10
11
12
--当赋值时,如果赋值一个不存在的索引,那么会把这个值赋值到newindex所指的表中,不会修改自己
meta7 = {}
myTable7 = {}
meta7.__newindex = {}
setmetatable(myTable7,meta7)
myTable7.age = 1
print(myTable7.age)
--nil
print(meta7.__newindex.age)
--1

--newindex也支持多层套用

可以用rewset方法取消newindex的作用

1
2
3
rawset(myTable7,"age",2)
print(myTable.age)
--2

获取元表

1
2
print(getmetatable(myTable6))
--table: 00000000011e1b80

Lua面向对象之封装

面向对象 类 都是基于table来实现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Object = {}
Object.id = 1

--为Object实现一个实例化的方法
function Object:new()
--self代表默认传入的第一个参数
local obj = {}
setmetatable(obj,self)
self.__index = self
return obj
end

local myObj = Object:new()
print(myObj.id)
--1

Lua面向对象之继承

实现一个用于继承的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--还是之前那个脚本
function Object:subClass(className)
_G[className] = {}
local obj = _G[className]
self.__index = self
obj.base = self
setmetatable(obj,self)
end

Object:subClass("Person")--将Person的元表设置为Ojbect
local p1 = Person:new()--将p1的元表设置为Person
print(p1.id)--在p1中找不到id,寻找元表index指向的Person,又找不到,继续在Person元表index指向的Object中寻找,找到id
--1

p1.id = 100
print(p1.id)
--100

local p2 = Person:new()
print(p2.id)
--1

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
--还是之前的脚本
Object:subClass("GameObject")
GameObject.posX = 0
GameObject.posY = 0
function GameObject:Move()
self.posX = self.posX +1
self.posY = self.posY +1
print(self.posX)
print(self.posY)
end
GameObject:subClass("Player")
local p1 = Player:new()
p1:Move()
--1
--1

function Player:Move()
self.base:Move()
print("移动")
end
p1:Move()
--[[
1
1
移动
]]

目前这种写法有很大问题

1
2
3
4
5
local p2 = Player:new()
p2:Move()
--2
--2
--p1和p2在共用变量

改写Player的Move方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Player:Move()
self.base.Move(self)
print("移动")
end
p1:Move()
p2:Move()
--[[
1
1
移动
1
1
移动
]]

面向对象汇总

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
--lesson15_OO.lua

--实现一个万物之父,所有对象的积累 Object
Object = {}
--实例化方法
function Object:new()
local obj = {}
self.__index = self
setmetatable(obj,self)
return obj
end

--继承
function Object:subClass(className)
_G[className] = {}
local obj = _G[className]
obj.base = self
self.__index = self
setmetatable(obj,self)
end

Object:subClass("GameObject")--算是声明GameObject的同时使GameObject继承Object
GameObject.posX = 0
GameObject.posY = 0
function GameObject:Move()
self.posX = self.posX +1
self.posY = self.posY +1
end

local obj = GameObject:new()
print(obj.posX)
--0
obj:Move()
print(obj.posX)
--1

local obj2 = GameObject:new()
print(obj2.posX)
--0

--多态
GameObject:subClass("Player")
function Player:Move()
--调用父类方法,一定要用点调用,传入自己
self.base.Move(self)
print("移动")
end
local p1 = Player:new()

print(p1.posX)
p1:Move()
print(p1.posX)
--[[
0
移动
1
]]

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
--系统时间
print(os.time)
--function: 0000000065ba1550

--自己传入参数得到时间
print(os.time({year = 2014, month = 8,day = 14}))
--1407988800

local nowTime = os.date("*t")
print(nowTime)
for k,v in pairs(nowTime) do
print(k,v)
end
print(nowTime.hour)
--[[
table: 00000000006a9900
wday 5
min 37
year 2023
month 4
isdst false
day 27
yday 117
hour 19
sec 52
19
]]
--现在是2023年4月27日19:38

数学运算

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
--绝对值
print(math.abs(-11))
--11

--弧度转角度
print(math.deg(math.pi))
--180.0

--三角函数
prit(math.cos(math.pi))
-- -1

--向下和向上取整
print(math.floor(23.6))
print(math.ceil(5.2))

--最大最小值
print(math.max(1,2))
print(math.min(4,5))

--小数分离,分成整数部分和小数部分
print(math.modf(1.2))

--幂运算
print(math.pow(2,5))

--随机数
--使用随机数之前一定要设置随机数种子,可以设置系统时间
math.randomseed(os.time)
print(math.random(100))
print(math.random(200))

--开方
print(math.sqrt(4))

其他

1
2
3
4
5
6
7
8
9
10
11
12
--lua脚本加载路径
print(package.path)
--[[
E:\lua-5.4.2_Win64_bin\lua\?.lua;E:\lua-5.4.2_Win64_bin\lua\?\init.lua;E:\lua-5.4.2_Win64_bin\?.lua;E:\lua-5.4.2_Win64_bin\?\init.lua;E:\lua-5.4.2_Win64_bin\..\share\lua\5.4\?.lua;E:\lua-5.4.2_Win64_bin\..\share\lua\5.4\?\init.lua;.\?.lua;.\?\init.lua;E:\Lua\5.1\lua\?.luac
]]

--这个值是可以改的
package.path = package.path ..";C:\\"
print(package.path)
--[[
E:\lua-5.4.2_Win64_bin\lua\?.lua;E:\lua-5.4.2_Win64_bin\lua\?\init.lua;E:\lua-5.4.2_Win64_bin\?.lua;E:\lua-5.4.2_Win64_bin\?\init.lua;E:\lua-5.4.2_Win64_bin\..\share\lua\5.4\?.lua;E:\lua-5.4.2_Win64_bin\..\share\lua\5.4\?\init.lua;.\?.lua;.\?\init.lua;E:\Lua\5.1\lua\?.luac;C:\
]]

垃圾回收

垃圾回收关键字:collectgarbage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--获取当前lua占用内存数 K字节 用返回值*1024就可以得到具体的内存占用字节数
print(collectgarbage("count"))
--24.3876953125

--进行垃圾回收
collectgarbage("collect")
print(collectgarbage("count"))
--22.521484375

--lua中的垃圾回收机制和C#的GC很类似,接触羁绊,就是变垃圾
--[[
test = {name = 123}
test = nil
这就相当于解除羁绊
]]

Unity热更新开发中,尽量不要使用自动垃圾回收