Unity 热更新学习笔记三:Lua语言
Lua语言有什么用?
在前两节笔记中,我们学习到了AssetBundle,这是对资源的热更新。但游戏逻辑也是会有Bug需要修改,或者添加新的需求。这时就需要对代码进行热更新。怎么办?我们可以使用Lua或者ILRuntime对代码进行热更新。这里先学习Lua,因为Lua技术比较老使用广泛,绝大多数公司代码热更新还是使用Lua来进行的。
Lua语言的特点?
1.轻量级:使用标准的C语言进行编写,编译后只有100k左右,可以方便的嵌入到其他程序中。
2.可拓展,提供了方便使用的接口。
在Unity中,Lua主要使用在xLua插件中,Unity程序在打包过程中C#会被最终转译为C++语言,使用Lua可以方便的与C++进行通信。(目前IOS平台已经不允许使用Lua热更新)
后面主要学习一些Lua与其他语言相异的一些语言特性:
注释:
-- 注释 --[[ 多行注释 ]]
Lua语言是一种解释性语言,变量类型是自动推到的,同时Lua中调用未定义的变量类型会为nil(相当于C++中的null)
Lua中不要轻易定义全局变量,因为其他用户也可能使用到这个全局变量并修改。
-- 全局变量 name = "CatSevenMillion" -- 局部变量 local name = "CatSevenMillion" -- 变量类型 type(name)
字符串:
-- 定义单行字符串 local name = "abc" -- 定义多行字符串 local name = [[ one two ]] -- 字符串拼接 -- C# : str1+str2 print(str1 .. str2) -- 自动类型转换 -- a="1" ,b="2" print(a+b) -- 返回结果为3 --获取字符串长度 print(#str)
操作符:
-- 不等于 a ~= b -- Lua 中没有++,--, +=, -=
逻辑控制:
-- if语句 if(a) then print("条件a达成") elseif(b) then print("条件b达成") else print("条件达成") end -- Lua没有switch逻辑,可以用if else代替 --while循环 while(n<3) do n = n+1 end -- do while循环 repeat n = n+1 until(n>3) -- for 循环, 第一个参数开始值,第二个参数结束值, 第三个参数是步长,没有时默认为1 for i = 1, #data , stride do i = i+1 end
迭代器:
-- 首先定义一个列表 data = {one = "cc","aa","bb",[4] = 3 , [-1] = 4 , ["two"] = "dd"} --连续索引数值迭代器 for k,v in ipairs(data) do print("k:" .. k .. ", v:" .. v) end --[[ 结果: k:1, v:aa k:2, v:bb ]] -- 所有数值迭代器 -- 优先遍历索引数值 for k,v in pairs(data) do print("K:" .. k .. ", V:" .. v) end --[[ 结果: K:1, V:aa K:2, V:bb K:one, V:cc K:-1, V:4 K:4, V:3 K:two, V:dd ]]
pairs与ipairs的区别:
pairs遍历table中的全部的key-vale, 而ipairs会依据key的数值从1開始加1递增遍历相应的table[i]值
pairs 会优先输出没有键的值,即先输出"val3" ,再到key1 = "val1",再 key2 = "val2"。
ipairs 只会输出没有键的值。即只输出"val3",其他不会输出。
pairs能够遍历表中全部的key,而且除了迭代器本身以及遍历表本身还能够返回nil;可是ipairs则不能返回nil,仅仅能返回数字0,假设遇到nil则退出。它仅仅能遍历到表中出现的第一个不是整数的key
-----------------------------------
ipairs与pairs的区别
https://blog.51cto.com/u_15064638/4513957
函数与表:
-- 定义函数 local func2 = function() print("这是一个函数") end --调用函数 func2() ---------------------------------------- -- 含参函数 local func3 = function(a,b) print(a+b) end --调用函数 func3(1,2) func3(1,2,3) -- *以上都是可以运行的,函数实参可以多于等于行参,但不能少于形参 ---------------------------------------- -- 无固定参数函数 local func4 = function(...) -- ... 的意思是无固定参数 -- 将无固定参数转换为table -- arg 是局部变量,如果不声明为local就会成为全局变量 local arg = {...} local total = 0 for k,v in pairs(arg) do totoal = total +v end end -- 将以下全部数据求和 func4(1,2,3,4,5,6) ---------------------------------------- -- 多个返回值的函数 function func5() return 1,2 end num1,num2 = func5() --[[ 结果: num1=1,num2=2 ]] ---------------------------------------- -- 函数作为索引 data = {one ="cc","aa"} data.func1 = function() print("data表中的func1函数") end -- 通过data调用func1函数 data.func1() -- 函数显示加入self对象,函数内部可以通过self来获取当前表内其他对象。 data.func3 = function(self) print(self.two) end --调用 *注意用冒号 data:func3()
文件加载与元表:
-- 加载文件 -- 加载文件时不可以有特殊字符例如 . ,.lua文件后缀不用添加,会自动补全 require("subfile/file1") ---------------------------------------------------- -- 加载文件时不会重复加载 require("subfile/file1") require("subfile/file1") -- 上述只会运行一次 ----------------------------------------------------- -- 检查文件加载状态 print(package.loaded["subfile/file1"]) -- 清除加载状态 package.loaded["subfile/file1"] = nil ----------------------------------------------------- -- 元表(metatable) -- 我们直接打印表时,显示的是表的内存地址,如下: local t1 = {1,2,3} print(t1) -- 结果 :table:00342FF2 -- 但是我们预期将表按照字符串的方式输出内容,可以使用metatable进行拓展 setmetatable( t1, --需要进行拓展的数据表 { -- 拥有拓展t1的元表,只需要在元表中实现一些特殊函数,t1就会拥有新的特性 --t1 会传递给t,命名是随便的 _tostring = function(t) -- 元方法,当被扩展的表被以string方式调用时同步调用 local format = "{" for k,v in pairs(t) do format = format .. v .. ', ' end format = format .. "}" return format end } );

浙公网安备 33010602011771号