Lua基础学习笔记和简单案例

Lua

1.循环:
a.while循环:while 条件 do… end
b.do while循环: repeat until… 满足条件跳出,结束
c.for语句: for i =1,5 do… end (默认递增,i会默认+1)
for i =1,5,2 do… end (自定义递增量,i会+2)

2.函数:声明:function 函数名()
end
a=function()
end

a.无参数无返回值:function F1( )
print(“F1”)
end
F1() -调用

F2=function ( ) -类似c#中的委托和事件写法,赋值形式
print(“F2”)
end
F2()

1,class 是引用类型,structs是值类型
既然class是引用类型,class可以设为null。但是我们不能将struct设为null,因为它是值类型。

2.资源管理系统-Addressable Asset
https://www.jianshu.com/p/e79b2eef97bf

3.Dictionary字典:实例化:Dictionary<键key,值value> 名字dic=new Dictionary<键key,值value>();
Dictionary<Tkey,Tvalue> dic=new Dictionary<Tkey,Tvalue>();
方法:

Dic.Add(key,value)给字典添加值
Dictionary[key]表示key所对应的值
ContainsKey(key)判断key是否存在
注意:方法首字母是大写,有小括号,属性第一个单词首字母小写后边单词首字母大写

嵌套字典
嵌套实例化:Dictionary<key,Dictionary<key,value>>dic=new Dictionary<key,Dictionary<key,value>>();

Instantiate函数实例化:Instantiate函数实例化是将original对象的所有子物体和子组件完全复制,成为一个新的对象。这个新的对象拥有与源对象完全一样的东西,包括坐标值等。
original:用来做复制操作的对像物体,源对象
position:实例化的对象的位置坐标
rotation:实例化的对象的旋转坐标(旋转四元数)
parent:实例化对象的父对象,就是给这个实例化对象找的爹,在完成实例化函数处理后,实例化对象将在父对象下,是父对象的子对象

b.有参数 :function F3( a )
print(a)
end
F3(1)
F3(“123”)
F3(true)
F3()
F3(1,2,3)-如果你传入的参数和函数个数不匹配。不会报错。只会补空nil或者丢弃
利用function关键字

c.有返回值:
function F4(a)
return a,“111”,true -多返回值,需要在前面申明多个变量接取即可,如果变量不够,不会报错,值接取对应位置的返回值.如果变量多了,也不会报错,会直接为nil
end
temp1,temp2,temp3 = F4(“oh”)
print(temp1)
print(temp2)
print(temp3)

d.函数的类型:F5=function ()
print(“F5”)
end
print(type(F5))

e.函数的重载:函数名相同,参数个数类型不同(因为Lua里面对传进来类型不关注,所以不太支持重载)
function F6()
print(“试试重载”)
end
function F6(str)
print(str)
end
F6()
-lua中.函数不支持重载,默认调用最后一个声明的函数

f.变长参数:function F7( … ) -利用…去表示变长
arg = {…}
-变长参数使用,用一个表存起来.再用它
for i=1,#arg do
print(arg[i])
end
end
F7(1,2,3,true,5)

g.函数嵌套:function F8()
return function ()
print(“函数嵌套2”)
end
end
f9 =F8()
f9()

–闭包在函数内部返回一个函数,这个改变了临时变量(传入参数)的生命周期
function F9(x)
return function (y)
return x + y
end
end
f10 =F9(11)
print(f10(5))

3.复杂数据类型table:所有复杂数据类型都是表

a.数组:表声明:lua中表(数组)索引从1开始,所以打印数组为0小标时。为nil。
#是通用的获取长度的关键字
在打印长度的时候,nil空被忽略了,它遍历到nil时候。会影响到#获取长度,会认为数组断了
a = {1,nil,true,“111”,5}
print(a[1])
print(a[2])
print(#a) --但是经我测试,长度还是正常没有打断

b.数组的遍历:
for i=1,#a do
print(a[i])
end

c.二维数组:
a = { {1,3,5},{“111”,“222”}}
print(a[2][2])

d.二维数组的遍历
a = { {1,3,5},{“111”,“222”}}
print(a[2][2])
for i=1,#a do
b=a[i]
for j=1,#b do
print(b[j])
end
end

e.自定义索引:
aa = {[0]=1,2,3,6,[-1]=4,5}
print(aa[0])
print(aa[-1])
print(aa[1])
print(aa[2])
print(aa[3])
print(#aa)

ab = {[1] = 1,[2] = 2,[3]=3,[6]=6}
print(#ab) --会打印到3,而不是6,因为间隔
ab = {[1] = 1,[2] = 2,[3]=3,[6]=6}
print(#ab) --相应也是打印到3

4.迭代器:迭代器遍历主要遍历表
#得到长度,但是并不准确,一般不用#遍历表
a={[0]=1,2,[-1]=3,4,5}
for i,k in ipairs(a) do
print(“ipairs遍历键值”…i…““…k)
end
–ipairs从1开始往后遍历,小于等于0的值得不到,只能找到连续索引的值,中间断序列,它无法遍历后面内容
for i,v in pairs(a) do
print(“pairs遍历键值”…i…”
”…v)
end
–pairs可以遍历所有键值

5.table实现字典:
a.字典:

b.字典的声明:a={[“name”] = “me”,[“age”] = 14,[“233”] = 23}
print(a[“name”])
print(a[“age”])
print(a[“233”])
print(a.name)
–访问单个变量,用中括号填键来访问或者可以.成员变量形式。但是不可以a.1,.后面不能是数字
改变:a[“name”] =“TLs”
添加/新增:a[“sex”] = false
删除:a[“sex”] = nil – 但实际不算是真正的删除

c.字典的遍历:一定要用pairs(因为Ipairs中断不可以遍历下去了)
for k in pairs(a) do
print(k)
print(a[k])
end

for ,v in pairs(a) do
print(
,v)
end
–遍历的话要遍历key才能遍历value。所以需要两个变量。也可以只遍历Key

d.类的结构体:lua中默认没有面向对象的,需要我们自己来实现
–c#使用类,实例化对象new 静态直接
lua中类的表现更像是一个类中有很多静态变量和函数
student = {
age = 1,
sex = true,
up = function ()
–这样写age和表中的age没有任何关系,它是一个全局变量
–print(age)
–要想在表内部函数里调用表本身的属性或者方法,一定要置顶是谁
–print(student.age) 表名.属性或表名.方法
print(“cold”)
end,
learn = function (t)
–第二种,能够在函数内部调用自己属性或者方法的方法
–把自己作为一个参数传进来,在内部访问
print(t.sex)
print(“调用内部sex”)
end

}
–声明表过后,在表外去声明表有的变量和方法
student.name = “iii”
–函数第三种声明方式
function student:speak1( )
print(“说话1”)
end

print(student.age)
print(student.name)
student.up()
student.speak1()
–在Lua中,.和冒号区别。冒号调用方法,:会默认把调用者作为第一个参数传入方法中.:在外部使用,在类内部无法使用
–student.learn(student)–lua中,有一个关键字self表示默认传入的第一个参数
student:learn()

–在Lua中有一个关键字self表示默认传入的第一个参数。

e.表的公共操作:
–表中table提供的一些公共方法
t1 = { {age = 1,name = “123”},{age = 2,name = “233”}}
t2 = {name = “III”,sex = true}

–插入
print(#t1)
table.insert(t1,t2)
print(#t1)
print(t1[1])
print(t1[2])
print(t1[3]) --因为有三个表
print(t1[3].sex)

–删除指定元素
table.remove(t1)
print(#t1)
print(t1[1].name) --可以观察到,传表进去。会移除最后一个索引的内容
print(t1[2].name)
print(t1[3])

–remove方法。传两个参数,第一个参数是要移除的表。第二个参数,是要移除内容的索引
table.remove(t1,1)
print(t1[1].name)

t2 = {5,2,7,9,6}
–传入要排序的表,默认降序排序
table.sort(t2)
for _,v in pairs(t2) do
print(v)
end
–传入两个参数,第一个是排序的表,第二个是排序规则的函数
table.sort(t2,function (a,b)
if a > b then
return true
end
end)
for _,v in pairs(t2) do
print(v)
end

–拼接
tb = {“123”,“456”,“789”,“1011”}
–连接函数,用于拼接表中的元素,返回值是个字符串,一般好像只能用于字符串和数字
str = table.concat( tb, “,”)
print(str)

6.多lua脚本执行:a.全局变量和本地变量:–全局变量
a = 1
b = true
for i = 1,3 do
c = “hi”
end
print©

–本地/局部变量的关键字-local,只在对应的语句块有作用
for i = 1,3 do
local d = “oh”
print(“循环中的d”…d)
end
print(d)

fun = function ()
t1 = “121121”
end
fun()
print(t1)

local tt2 = 1
print(tt2)

b.多脚本执行:–关键字 require(“脚本名”) require(‘脚本名’)
require(“ceshi”)
print(testA)
print(testB)

c.脚本卸载:–如果是require加载执行的脚本,加载一次过后不会再被执行
require(“ceshi”)
–package.loaded[“脚本名”]
–返回值是boolean,意思是该脚本是否被执行
print(package.loaded[“ceshi”])
–卸载已经执行过的脚本
package.loaded[“ceshi”] = nil
print(package.loaded[“ceshi”])

–require执行一个脚本时,可以在脚本最后返回一个外部希望获取的内容
local testLA = require(“ceshi”)
print(testLA)

d.大G表:
–大G表声明:_G是一个总表。他将我们声明的所有全局变量都存储在其中
–大G表不会存本地变量
for k,v in pairs(_G) do
print(k,v)
end

print(“test”)
testA = “hungry”
local testB = 2

return testB

7.特殊用法:
a.多变量赋值:a,b,c = 1,2,“123”
print(a)
print(b)
print©
–多变量赋值,如果后面的值不够,会自动补空。如果后面的值多了,会自动省略
a,b,c = 1,2
print(a)
print(b)
print© --nil

b.多返回值:function Test()
return 10,11,12
end
–多返回值时,你用几个变量接,就有几个值
–如果少了,就少接几个,如果多了就自动补空
a,b,c=Test()
print(a)
print(b)
print©

c. and or:–and or可以连接boolean,任何东西都可以连接
–lua中只有nil和false才认为是假
–“短路”-对于and来说,有假则假,对于or来说,有真则真。所以他们只需要判断第一个是否满足,就会停止计算
print(1 and 2)
print(0 and 1)
print(nil and 1)
print(false and 2)
print(true and 3)

8.协同程序:a.协程的创建:–coroutine.creat()
fun = function ()
print(111)
end

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

–coroutine.wrap()
co2 = coroutine.wrap(fun)
print(co2)
print(type(co2))

b.协程的运行:–creat创建方式的运行方式
coroutine.resume(co)
–wrap创建方式的运行方式
co2()

c.协程的挂起:fun2 = function ( )
local i = 1
while true do
print(i)
i = i+1
–协程的挂起函数
print(coroutine.status(co3))
print(coroutine.running())
coroutine.yield(i)
end
end
co3 = coroutine.create(fun2)
–默认第一个返回值是协程是否启动成功,第二个返回值是yield里面的返回值
isstart,tempI = coroutine.resume(co3)
print(isstart,empI)
isstart,tempI = coroutine.resume(co3)
print(isstart,tempI)
isstart,tempI =coroutine.resume(co3)
print(isstart,tempI)

co4 = coroutine.wrap(fun2)
–这种方式,在你yield有返回值的时候,第一个参数直接就是yield返回的数值
co4()
co4()

d.协程的状态:–coroutine.status(协程对象)
–dead 结束
–suspended 暂停
–running 进行中
print(coroutine.status(co3))
print(coroutine.status(co))

–这个函数可以得到当前正在运行的协程的线程号
print(coroutine.running())

8.元表:
a.元表概念:
–任何表表都可以作为另一个表变量的元素
–任何表变量都可以有自己的元表(爸爸)
–作用:当我们子表中进行一些特定操作时,会执行元表中的内容

b.设置元表:meta = {}
mytable = {}
–设置元表函数
–第一个参数,子表,第二个参数,元表
setmetatable(mytable,meta)

c.元表特定操作__tostring:
meta2 = {
–当子表要被当作字符串使用,会默认调用这个元表中tostring方法
__tostring = function (t)
return t.name
end
}
mytable2 = {
name = “so so cold”
}
–设置元表函数
–第一个参数,子表,第二个参数,元表
setmetatable(mytable2,meta2)
print(mytable2)

d.元表特定操作__call:
meta3 = {
–当子表要被当作字符串使用,会默认调用这个元表中tostring方法
__tostring = function (t)
return t.name
end,
–当子表被当作一个函数来使用时,会默认调用这个__call中的内容
__call = function (a)
print(a)
print(“i want to go home”)
end
}
mytable3 = {
name = “so so cold”
}
–设置元表函数
–第一个参数,子表,第二个参数,元表
setmetatable(mytable3,meta3)
mytable3(1) --把子表当作函数调用。就会调用元表__call方法。__call在直接调用表时候就是调用这个函数,当传参数时候,默认第一个参数是调用者自己(就是表)

e.元表特定操作__运算符重载:meta4 = {
–当子表使用+运算符,会调用该方法
__add = function (t1,t2)
return 5
end,
__mul = function (t1,t2)
return 0
end,
__sub = function (t1,t2)
return 1
end,
__div = function (t1,t2)
return 2
end,
__mod = function (t1,t2)
return 3
end,
__pow = function (t1,t2)
return 4
end,
__eq = function (t1,t2)
return true
end,
__lt = function (t1,t2)
return true
end,
__le = function (t1,t2)
return true
end,
__concat = function (t1,t2)
return true
end
}
mytable4 = {age = 1}
setmetatable(mytable4,meta4)
mytable5 = {age = 2}
print(mytable4+mytable5)
–如果用条件运算符比较两个对象,则两个对象的元表要一致,才能准确调用这个方法。但是这里mytable4和Mytable5不是同个元表

f.元表特定操作__index和__newIndex:
meta6father = {
age = 1
}
meta6father.__index = meta6father
meta6 = {
–age = 1,
}
–__index的赋值写在表外面初始化
meta6.__index = meta6
–meta6.__index = {age = 2}
mytable6 = {}
setmetatable(meta6,meta6father)
setmetatable(mytable6,meta6)
–__index当子表中找不到某一个属性时,会到元表中__index指定的表去找索引

–得到元表的方法
print(getmetatable(mytable6))
print(mytable6.age)
–rawget当我们使用它时候,会去找自己身上有没有这个变量,不会去元表找
print(rawget(mytable6,“age”))
–__newIndex当赋值时,如果赋值一个不存在的索引,那么会把这个值赋值到newindex所指的表中,不会修改自己.
meta7 = {
}
meta7.__newindex = {}
mytable7 = {}
setmetatable(mytable7,meta7)
mytable7.age = 1
print(mytable7.age)
print(meta7.__newindex.age)
–rawset会忽略newindex的设置,只会改自己的变量
rawset(mytable7,“age”,2)
print(mytable7.age)

9.面向对象:
a.封装:–所有面向对象,类其实都基于table实现
obj = {}
obj.id = 1

function obj:Test()
print(self.id)
end
–冒号会自动调用这个函数对象,作为第一个参数传入的写法
function obj:new()
–self代表我们默认传入的第一个参数
–对象就是变量。返回一个新的变量,返回出去的内容,本质上就是表对象
local object = {}
–元表知识__index当找自己的变量找不到时,就会去找元表当中__index指向的内容
self.__index = self --像是实例化对象
setmetatable(object,self)
return object
end
local myobj = obj:new()
print(myobj)
print(myobj.id) --设置了空表,但是能得到是因为我们设置了元表,并且设置了元表的Index
myobj:Test()
–对空表中声明一个新的属性,叫做id
myobj.id = 2
print(obj.id)
myobj:Test()

b.继承:–所有面向对象,类其实都基于table实现
obj = {}
obj.id = 1

function obj:Test()
print(self.id)
end
–冒号会自动调用这个函数对象,作为第一个参数传入的写法
function obj:new()
–self代表我们默认传入的第一个参数
–对象就是变量。返回一个新的变量,返回出去的内容,本质上就是表对象
local object = {}
–元表知识__index当找自己的变量找不到时,就会去找元表当中__index指向的内容
self.__index = self --像是实例化对象
setmetatable(object,self)
return object
end
local myobj = obj:new()
print(myobj)
print(myobj.id) --设置了空表,但是能得到是因为我们设置了元表,并且设置了元表的Index
myobj:Test()
–对空表中声明一个新的属性,叫做id
myobj.id = 2
print(obj.id)
myobj:Test()

–c# class 类名 : 继承类 ,写一个用于继承的方法
function obj:subClass(className)
–_G知识点,是总表。全局变量都以键值对形式存在其中
_G[className] = {}
–写相关继承,用到元表
local object = _G[className]
self.__index = self
setmetatable(object,self)
end
–[[print(_G)
_G[“a”] = 1
_G.b = “111”
print(a)
print(b)]]

–通过这个字符串形式给里面加了一个空表
obj:subClass(“Person”)
print(Person)
print(Person.id) --因为前面写的实例化了index

c.多态:–相同行为 不同表象 就是多态
–相同方法,不同执行逻辑,就是多态
obj: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”)
function player:move()
–base.move()需要去subClass里去自定义个base
–self.base:move() --因为传进去的self不要为空,这里base指的是gameobject表
–这种方式调用是把基类表作为第一个参数传入了方法中
–避免把基类表传入到方法中,这样就相当于公用一张表的属性。所以需要利用.调用。就需要self.base.move(self),把自己传入到第一个参数
self.base.move(self)
end
local p1 =player:new()
p1:move()
p1:move()
local p2 = player:new()
–目前这种写法,有坑,不同对象使用的成员变量居然是相同的成员变量
p2:move()

d.总结:object = {}
–封装
function object:new()
local obj = {}
–给空对象设置元表,以及__index
self.__index = self
setmetatable(obj,self)
return obj
end
–继承
function object:subClass(className)
– 根据名字生产一张表,就是一个类
_G[className] = {}
local obj = _G[className]
–设置自己的父类
obj.base = self
–给子类设置元表,以及__index
self.__index =self
setmetatable(obj,self)
end

–声明一个新的类
object:subClass(“GameObject”)
–成员变量
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)
obj:move()
print(obj.posy)

local obj2 = GameObject:new()
print(obj2.posx)
obj2:move()
print(obj2.posy)

–声明一个新的类,player继承gameobject
GameObject:subClass(“player”)
–多态重写了gameobject的Move方法
function player:move()
–base调用父类方法,用.自己传第一个参数
self.base.move(self) --不能用冒号,因为会传入的是gameobject
end
local p1 = player:new()
print(p1.posx)
p1:move()
print(p1.posx)

10.自带库:a.自带库:string、table

b.时间:系统时间
print(os.time())
print(os.time({year = 2020, month = 11,day = 1}))
–os.date(“*t”)
local nowTime = os.date(“*t”)
print(nowTime)
for k,v in pairs(nowTime) do
print(k,v)
end
print(nowTime.hour)

c.数学运算:print(math.abs(-11))
print(math.deg(math.pi))
print(math.cos(math.pi))
print(math.floor(2.6))
print(math.ceil(5.2))
print(math.max(1,3))
print(math.min(4,8))
print(math.modf(1.3))
print(math.pow(2,5))
math.randomseed(os.time())
print(math.random(100))
print(math.random(100))
print(math.sqrt(4))

d.路径:–lua脚本加载路径
print(package.path)
package.path =package.path … " "
print(package.path)

11.lua垃圾回收:
a.垃圾回收关键字collectgarbage获取当前Lua占用内存数,k字节,用返回值×1024就可以得到具体的内存占用字节数
test = {id = 1, name = “1111”}
print(collectgarbage(“count”))
–lua中的极致和c#中垃圾回收机制类似,解除羁绊(nil)就是变垃圾
test = nil
–进行垃圾回收
collectgarbage(“collect”)
print(collectgarbage(“count”))

猜你喜欢

转载自blog.csdn.net/qq_43614246/article/details/129197961