【Unity】Lua入门


一、Lua基础

1.1 变量类型

   nil(空)、boolean、number(数字-不区分数字类型)、string、function、table、userdata(自定义)、thread(线程)

1.2 特点

   动态类型、弱类型、大小写敏感、默认全局、带GC


二、运算符

2.1 数学运算

   5 + 3 = 8
   5 - 3 = 2
   5 * 3 = 15
   5 // 3 = 1
   5 / 3 = 1.6666666666667
   5 % 3 = 2
   5.5 % 3 = 2.5
   5 ^ 3 = 125.0
   不存在:++ += =+

2.2 关系运算

   < > >= <= == ~=

2.3 逻辑运算

   and(&&):逐个判断,遇到false返回
   or(||) :逐个判断,遇到true返回
   not(!)
-注意
a、false与nil 为false
b、没有三目运算符(? : )

--模拟三目运算
function JudgeAge(age)
	return age > 18 and "adult" or "child"
end

result = JudgeAge(20) print(result)--adult
result = JudgeAge(15) print(result)--child

c、and优先级大于or
d、除…和^为右结合优先,其余为左结合优先

2.4 位运算

a = 3 --0000 0011
b = 5 --0000 0101

result = a&b print(result)  -- a&b = 1
result = a|b print(result)  -- a|b = 7
result = ~b print(result)   -- ~b = -6
result = a<<2 print(result) -- a<<2 = 12
result = b>>1 print(result) -- b>>1 = 2

-注意
   lua5.1使用位运算,需引入第三方库,如bitlib
   lua5.2使用位运算,使用内置库bit32
   lua5.3使用位运算,可直接使用运算符

2.5 其它

2.5.1#

解释:相当于Length或Count
a、

s= "test"

result = #s
print(result)--4

b、
1)

nums = {1,nil,3,nil,4}

result = #nums
print(result )--5

2)

nums = {1,nil,3,nil,4,nil}

result = #nums
print(result )--3

3)

nums = {1,nil,3,nil,4,nil,x=100,y=200}

result = #nums
print(result )--3

注意
   #返回的个数,不包含Table中自定义键的键对数。
   当最后一个默认键对的值为nil时,不统计所有键值为nil的键对数。

2.5.2 . .

解释:连接字符串

function Concat(a,b)
	return a..b
end

result = Concat("str","ing")
print(result)--string

-注意:性能消耗大


三、数据结构-Table

3.1 说明

   Lua唯一数据结构,下标从1开始,以键值对的方式存储(nil不能作为键)

3.2 举例

定义:

table = {1,"a",x = 100,y = 200,x = 300,2,table1 = {["x"] = 101, 2}}
table.z = 50
table[7] = 7

使用:

print(table[1])--1
print(table[2])--a
print(table["x"])--300
print(table.y)--200
print(table[3])--2
print(table["z"])--50
print(table[7])--7
print(table.table1.x)--101
print(table.table1[1])--2

print(table[10])--nil
print(table.table1["z"])--nil

3.3 遍历方式

3.3.1 pairs

for k,v in pairs(table) do
	print(k,":",v)
end

输出结果:
     1 : 1
     2 : a
     3 : 2
     y : 200
     z : 50
     table1 : table: 0x21d76d0
     7 : 7
     x : 300

3.3.2 ipairs

for k,v in ipairs(table) do
	print(k,":",v)
end

输出结果:
     1 : 1
     2 : a
     3 : 2

-注意
a、定义:table = {1,2,3,4,5}
     table[7] = 7

for k,v in ipairs(table) do
	print(k,":",v)
end

输出结果:
     1 : 1
     2 : 2
     3 : 3
     4 : 4
     5 : 5

b、定义:table = {1,2,3,4,5,6}
     table[7] = 7

for k,v in ipairs(table) do
	print(k,":",v)
end

输出结果:
     1 : 1
     2 : 2
     3 : 3
     4 : 4
     5 : 5
     6 : 6
     7 : 7


四、语句

4.1 添加注释

   单行:–
   多行:–[[ ]]
   嵌套:[=[ ]=]

4.2 赋值

   单变量:a = 100
   多变量:a,b = 100,“string”
   交换: a,b = b,a

4.3 分支

num = 100

if num > 100 then
	print("more")
elseif num > 50 then
	print("middle")
else 
	print("less")
end

4.4 循环

a、for循环
   从1开始,100结束,每次+2,

for i = 1,100,2 do
	print("i = ",i)
end

b、while循环
   当i<10

i = 0
while i < 10 do
	i = i + 1	
	if a>= 8 do
		break
	end
end

c、repeat循环
   i=0,i+2,直到i>=10

i = 0
repeat 
	i = i + 2
until i>=10

   Lua没有关键字:continue


五、函数

5.1 定义方式

a、基础写法

add = function(a,b)
	return a+b
end

result = add(1,2)
print(result)--3

b、语法糖写法

function add(a,b)
	return a+b
end

result = add(1,2)
print(result)--3

-注意

 传入:
   1)定义两个参数,传入三个参数,不报错,第三个直接丢弃
   2)定义三个参数,传入两个参数,若不使用未传参的参数不报错

 传出:
   1)返回三个返回值,接收两个返回值,不报错,第三个直接丢弃
   2)返回两个返回值,接收三个返回值,不报错,接收到的第三个为nil

5.2 多返回值

function fun(a,b)
	return a+b,a*b
end

sum,product = fun(1,2)

print(sum)--3
print(product)--2

5.3 高阶函数

解释:Lua中的函数,可作为参数传递

function add(a,b)
	return a + b
end

function fun(f,a,b)
	return f(a,b)
end

result = fun(add,1,2)
print(result)--3

5.4 可变参数

解释:当参数个数不确定时,用…代替

function add(...)
	local sum = 0
	local arg = {...}
	
	for k,v in ipairs(arg) do
		sum = sum +v
	end
	
	return sum
end

result = add(1,2,3,4)
print(result)--10

六、函数库

6.1 引用方式

a、基础写法

str = "string"

result = string.upper(str)
print(result)--STRING

b、语法糖写法-不适用于多参数

str = "string"

result1 = str : upper()
print(result1)--STRING

result2 = str.upper(str)
print(result2)--STRING

6.2 函数库浏览

Lua5.3参考手册


七、协程

7.1 create示例

1)

co = coroutine.create(
	function()
		print("start")--(1)
		coroutine.yield()
		print("after yield")--(3)
	end
)

coroutine.resume(co)
print("yield")--(2)
coroutine.resume(co)

输出:
   (1)start
   (2)yield
   (3)after yield

2)

co = coroutine.create(
	function(num1,num2)
		print("First num1 =",num1," num2 =",num2)--(1)
		temp1,temp2 = coroutine.yield("startCor",1)
		print("Second num1 =",num1," num2 =",num2)--(3)
		print("Second temp1 =",temp1," temp2 =",temp2)--(4)
	end
)

result1,result2,result3 = coroutine.resume(co,100,101)
print(result1, result2, result3)--(2)
coroutine.resume(co,200,201)

输出:
   (1)First num1 = 100 num2 = 101
   (2)true startCor 1
   (3)Second num1 = 100 num2 = 101
   (4)Second temp1 = 200 temp2 = 201

7.2 wrap示例

1)

fun = coroutine.wrap(
	function()
		print("start")--(1)
		coroutine.yield()
		print("after yield")--(3)
	end
)

fun()
print("yield")--(2)
fun()

输出:
   (1)start
   (2)yield
   (3)after yield

2)

fun= coroutine.wrap(
	function(num1,num2)
		print("First num1 =",num1," num2 =",num2)--(1)
		temp1,temp2 = coroutine.yield("startCor",1)
		print("Second num1 =",num1," num2 =",num2)--(3)
		print("Second temp1 =",temp1," temp2 =",temp2)--(4)
	end
)

result1,result2 = fun(100,101)
print(result1, result2)--(2)
fun(200,201)

输出:
   (1)First num1 = 100 num2 = 101
   (2)startCor 1
   (3)Second num1 = 100 num2 = 101
   (4)Second temp1 = 200 temp2 = 201

7.3 create与wrap

定义:
   co = coroutine.create()
   fun = coroutine.wrap()

不同点:
   1)返回类型不同。
      create()返回类型为thread。
      wrap()返回类型为function。
   2)执行方式不同。
      create依靠coroutine.resume(co)。
      wrap依靠fun()。
   3)默认返回不同。
      coroutine.resume()默认返回bool-即是否成功执行。
      fun()默认返回nil。
   4)调用Dead不同。
      coroutine.resume()调用处于dead状态的协程无效果。
      fun()调用处于dead状态的协程报错。

相同点:
   1)每次调用coroutine.resume(co)或fun(),执行协程一部分代码,即可调用次数与coroutine.yield数量有关。
   2)
    每次调用coroutine.resume(co)或fun()传入的参数,作为coroutine.yield的传出参数返回。
    每个coroutine.yield的传入参数作为对应coroutine.resume(co)或fun()的传出参数返回。
    仅第一次调用coroutine.resume(co)或fun()传入的参数,作为create()或wrap()的传入参数。

-注意
   Lua中的协程可以无coroutine.yield

   协程生命周期:start-suspend-running-dead-end
   说明:通过coroutine.resume(co)或fun(),使状态由suspend转为running,之后可通过coroutine.yield转回suspend


八、元表与元方法

8.1 元表

(1)lua中的每个值都可以有一个元表,只是table和userdata可以有各自独立的元表,而其他类型的值则共享其类型所属的单一元表。
(2)lua代码中只能设置table的元表,至于其他类型值的元表只能通过C代码设置。
(3)多个table可以共享一个通用的元表,但是每个table只能拥有一个元表。
(4)我们称元表中的键为事件(event),称值为元方法(metamethod)。
(5)可通过函数getmetatable查询任何值的元表。
(6)可通过函数setmetatable替换表的元表
详细解释

8.2 元方法

8.2.1 __index

定义: 索引 table[key]。 当 table 不是表或是表 table 中不存在 key 这个键时,这个事件被触发。 此时,会读出 table 相应的元方法。
尽管名字取成这样, 这个事件的元方法其实可以是一个函数也可以是一张表。

解释
   __index用于查询键对应的值。
   1)首先判断table中的是否存在想要查询的键,如果存在则返回
   2)如果不存在或table不是表,则判断table是否存在元表
   3)如果存在元表,则判断元表中是否有__index方法
   4)如果存在__index方法,则调用该方法。
      --如果该方法是函数则调用该函数,并将table作为第一个参数。
      --如果该方法是表,则将该表作为初始table,从第一步开始判断。

(1)如果__index方法是一个函数,则以 table 和 key 作为参数调用它

table = {a = 1}
metatable = {
	__index = function(table,key)
		return 123
	end
}

print(table["b"])---nil

setmetatable(table,metatable)

print(table["b"])---123

(2)如果__index方法是一张表,最终的结果就是以 key 取索引这张表的结果。 (这个索引过程是走常规的流程,而不是直接索引, 所以这次索引有可能引发另一次元方法。)

table = {a = 1}
metatable = {
	__index = {
		b = 2
	}
}

print(table["b"])---nil
print(table["c"])---nil

setmetatable(table,metatable)

print(table["b"])---2
print(table["c"])---nil

8.2.2 __newindex

定义:索引赋值 table[key] = value 。 和索引事件类似,它发生在 table 不是表或是表 table 中不存在 key 这个键的时候。 此时,会读出 table 相应的元方法。
同索引过程那样, 这个事件的元方法即可以是函数,也可以是一张表。 一旦有了 “newindex” 元方法, Lua 就不再做最初的赋值操作。 (如果有必要,在元方法内部可以调用 rawset 来做赋值。)

解释
   __newindex用于对键赋值。
   1)首先判断table中的是否存在想要查询的键,如果存在则重新赋值该键
   2)如果不存在或table不是表,则判断table是否存在元表
   3)如果存在元表,则判断元表是否存在__newindex方法
   4)如果存在__newindex方法,则调用该方法。
      --如果该方法是函数则调用该函数,并将table作为第一个参数传入。
      --如果该方法是表,则将该表作为初始table,从第一步开始判断。
   5)如果table不存在元表或元表不存在__newindex方法,且table是表,则在当前表新增键值对。

(1)如果是一个函数, 则以 table、 key、以及 value 为参数传入。

table = {a = 1}
metatable = {
	__newindex = function(table,key,value)
	end
}

print(table["b"])---nil
print(table["c"])---nil

table["b"] = 2
setmetatable(table,metatable)
table["c"] = 3

print(table["b"])---2
print(table["c"])---nil
table = {a = 1}
metatable = {
	__newindex = function(table,key,value)
		--table[key] = value --stack overflow 死循环
							 --t["c"]=3 -> mt.__newindex () ->  table[key]=value -> mt.__newindex () -> table[key]=value -> ...
		rawset(table,key,value)
	end
}

print(table["b"])---nil
print(table["c"])---nil

table["b"] = 2
setmetatable(table,metatable)
table["c"] = 3

print(table["b"])---2
print(table["c"])---3

(2) 如果是一张表, Lua 对这张表做索引赋值操作。 (这个索引过程是走常规的流程,而不是直接索引赋值, 所以这次索引赋值有可能引发另一次元方法。)

local k = {}
local metatable = {
	__newindex = k
}
local table = {}

setmetatable(table, metatable)

print("赋值前:")--赋值前:
for k,v in pairs(k) do
	print(k ,v)--无输出
end

table[1] = 20

print("赋值后:table表中的值:")--赋值后:table表中的值:
for k,v in pairs(table) do
	print(k ,v)--无输出
end

print("赋值后:k表中的值:")--赋值后:k表中的值:
for k,v in pairs(k) do
	print(k ,v)--1	20
end

详细解释–文章

详细解释–视频

8.2.3 __call

定义:函数调用操作 func(args)。 当 Lua 尝试调用一个非函数的值的时候会触发这个事件 (即 func 不是一个函数)。 查找 func 的元方法, 如果找得到,就调用这个元方法, func 作为第一个参数传入,原来调用的参数(args)后依次排在后面。

解释
   当把非函数table当做函数使用时,
   先判断table是否存在对应元表,
   如果存在则判断元表中是否存在__call方法,
   如果存在__call方法,且该方法是函数则调用该方法,
   并将table当做第一个参数传入,其余参数依次排在后面。

function fun(table,x,y) 
	return table.n+x+y 
end

table = {}
table.n = 100

metatable = {}
metatable.__call = fun

setmetatable(table,metatable)

print(table(1,2))--103

九、面向对象(Object Oriented)

9.1 模拟对象

1)初始版本

local monster = {
	name = "Monster1",
	HP = 100,
	pos = {x=100,y=200}
}

monster.TakeDamage = function(self,damage)
	self.HP = self.HP - damage
end

monster.TakeDamage(monster,10)

result = monster.HP
print(result)--90

2)语法糖版本

local monster = {
	name = "Monster1",
	HP = 100,
	pos = {x=100,y=200}
}

function monster:TakeDamage(damage)
	self.HP = self.HP - damage
end

monster:TakeDamage(10)

result = monster.HP
print(result)--90

3)合并版本

local monster = {
	name = "Monster1",
	HP = 100,
	pos = {x=100,y=200},
	TakeDamage = function(self,damage)
		self.HP = self.HP - damage
	end
}

monster:TakeDamage(10)

result = monster.HP
print(result)--90

9.2 模拟类

1)初始版本

CMonster = {
	name="Monster",
	HP=100,
	TakeDamage = function(self,damage)
		self.HP = self.HP - damage
	end,
	ShowInfo = function(self)
		print(self.Name,self.HP)
	end
}

function CMonster:new(name,hp,x,y)
	local obj = {}
	obj.Name = name
	obj.HP = hp
	obj.X = x
	obj.Y = y
	setmetatable(obj, {__index = CMonster})
	return obj
end

local obj1 = CMonster:new("Monster1",100,100,101)
obj1:ShowInfo()--Monster1 100
obj1:TakeDamage(20)
obj1:ShowInfo()--Monster1 80

2)优化版本

CMonster = {
	name="Monster",
	HP=100,
	TakeDamage = function(self,damage)
		self.HP = self.HP - damage
	end,
	ShowInfo = function(self)
		print(self.Name,self.HP)
	end
}

CMonster.__index = CMonster

function CMonster:new(name,hp,x,y)
	local obj = {}
	obj.Name = name
	obj.HP = hp
	obj.X = x
	obj.Y = y
	setmetatable(obj, CMonster)
	return obj
end

setmetatable(CMonster,{__call = function(self,name,hp,x,y)
	return self:new(name,hp,x,y)
end
})

local obj1 = CMonster("Monster1",100,100,101)
obj1:ShowInfo()--Monster1 100
obj1:TakeDamage(20)
obj1:ShowInfo()--Monster1 80

9.3 模拟继承

说明:8.2脚本文件名为Monster.lua

local monster = require("Monster")--继承Monster.lua

local MagicMonster = {
	MP =200,
	Attack = function(self,consume)
		self.MP = self.Mp - consume
	end
}

setmetatable(MagicMonster,{
	__index = monster,
	__call = function(self,name,hp)
		local obj = CM(name,hp)
		setmetatable(obj,{__index = MagicMonster})
		return obj
	end
})

local magicMonster1 = MagicMonster("MagicMonster1 ",100)

magicMonster1 :ShowInfo()--MagicMonster1 100
magicMonster1 :TakeDamage(20)
magicMonster1 :ShowInfo()--MagicMonster1 80

9.4 模拟多态

说明:8.2脚本文件名为Monster.lua

local monster = require("Monster")--继承Monster.lua

local MagicMonster = {
	MP =200,
	Attack = function(self,consume)
		self.MP = self.Mp - consume
	end
}

setmetatable(MagicMonster,{
	__index = monster,
	__call = function(self,name,hp)
		local obj = CM(name,hp)
		setmetatable(obj,{__index = MagicMonster})
		return obj
	end
})

local magicMonster1 = MagicMonster("MagicMonster1 ",100)

magicMonster1 :ShowInfo()--MagicMonster1 100

function MagicMonster:ShowInfo()
	print("Magic Monster:", self.name, self.HP)
end

magicMonster1 :ShowInfo()--Magic Monster: MagicMonster1 80

9.5 模拟私有成员

1)直接封装

function GetMonster()
	local self = {HP = 123, Name = "monster"}
	
	local function GetHP()
		return self.HP
	end
	
	local function GetName()
		return self.Name
	end
	
	local function TakeDamage(_,count)
		self.HP = self.HP - count
		if self.HP <= 0 then
			self.HP = 0
		end
	end
	
	return {GetHP = GetHP, TakeDamage = TakeDamage, GetName = GetName}
end

local monster = GetMonster()

print(monster:GetHP())--123
monster:TakeDamage(20)
print(monster:GetHP())--103
monster.HP = 100
print(monster:GetHP())--103

2)元表封装

local Monster = {}
Monster.HP = 100
Monster.Type = "Monster"

function Monster:GetHP()
	return self.HP
end

function Monster:TakeDamage(damage)
	self.HP = self.HP - damage
end

function Monster:SetHP(hp)
	self.HP = hp
end

function Monster.new()
	local obj = {HP = Monster.HP}
	setmetatable(obj, Monster)
	Monster.__index = {GetHP = Monster.GetHP, TakeDamage = Monster.TakeDamage}
	Monster.__newindex = function(table,key,value)
		if key == "Type" then
			print("Forbiden operate.")
			return
		end
		rawset(table,key,value)
	end
	return obj
end

return Monster
local monster = require("Monster")
local obj = monster:new()
print(obj:GetHP())--100
obj:TakeDamage(10)
print(obj:GetHP())--90
--obj:SetHP(200) --报错 该方法为私有方法,不可访问

print(obj.Type)--Monster
obj.Type = "Monster Test"--Forbiden operate.
print(obj.Type)--Monster

print(obj.MP)--nil
obj.MP = 100
print(obj.MP)--100

十、闭包

function counter()
	local i = 0
	return function()
		i = i + 1
		return i
	end
end

local c1 = counter()
print(c1())--1
print(c1())--2
print(c1())--3

local c2 = counter()
print(c2())--1
print(c2())--2
print(c2())--3

定义:通过调用含有一个内部函数加上该外部函数持有的外部局部变量(upvalue)的外部函数(就是工厂)产生的一个实例函数
闭包详解


十一、关键字

11.1 local

   lua中变量默认为全局变量,加local进行限制,转变为局部变量。


参考

Lua5.3参考手册:传送门
VipSkill-Lua语法入门:传送门
Lua在线编程:传送门

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值