Lua热更新解决方案
文章目录
- Lua热更新解决方案
- 1.AB包
- 1.1 AB包概述
- 1. 从0开始的Lua语法
- 1.1 HelloWorld
- 1.2 数据类型
- 1.3 字符串
- 1.4 运算符
- 1.5 条件语句
- 1.6 循环语句
- 1.7 函数
- 1.8 数组
- 1.9 迭代器
- 1.10 字典,类,对象
- 1.11 多脚本执行
- 1.12 特殊语法
- 1.13 协程
- 1.14 元表
- 1.15 面向对象
- 1.16 库函数
1.AB包
1.1 AB包概述
AB包:特定于平台的资产压缩包,类似压缩文件,资产包括 模型,贴图,预设体,音效,材质球等。
Resources和AB包的区别:
Resources打包时为只读,无法修改。
AB包存储位置和压缩方式可自定义,后期可以动态更新。
AB包可以减小包体大小,并且实现资源或者脚本的热更新。
热更新的基本规则:
Tip:C#脚本无法打成AB包,这也是我们学习Lua的原因。
ABBrowser参数相关 : build页面:
1. 从0开始的Lua语法
1.1 HelloWorld
--单行注释内容
--Lua语句可以省略分号
--[[多行注释1]]
--[[多行注释2]]--
print("Hello World")
print("你好 Lua")
1.2 数据类型
--lua变量声明不需要声明类型
a = nil;
print(a);
--nil也是一种数据类型
--所有的数字类型都是number
a = 1
print(a)
a = 1.2
print(a)
--单引号或双引号都是字符串string
a = "123456"
print(a)
a = true
print(a)
--查看类型(type本身返回值是string)
print(type(a)) --boolean
--常见的四种类型:number,string,boolean,nil
--复杂的四种变量类型:function,table,userdata,thread
1.3 字符串
str = "slkajdd哈哈"
--字符串的长度
--中文字符在Lua中占三个长度
print(#str);
--转义字符
print("123\n123")
--多行打印字符串
s = [[我是
哈哈
嘿嘿]]
--字符串(不仅限于字符串)拼接
print("123" .. "456")
--替换符
print(string.format("我今年 %d 岁了",18))
s = "abca"
--其他类型转换为字符串
print(tostring(s))
--小写转大写
print(string.upper(str));
--大写转小写
print(string.lower(str));
--反转字符串
print(string.reverse(s))
--字符串查找索引
print(string.find(s,"a")) -- 1 1(双返回值)
--字符串截取
print(string.sub(s,2,3)) -- bc
--字符串修改
print(string.gsub(s,"a","b")) -- bbcb 2(双返回值)
--字符转ASCII
print(string.byte("Lua",1)) --(L)76
print(string.byte("A",1)) --(A)65
--ASCII转为字符
print(string.char(65)) --A
1.4 运算符
-- +-*/%都一样,但没有 += /= ++ --等等
--与C#不同的一点
print("123.4" + 1) --124.4
--幂运算 ^
print(2^10)
--不等号
print(8 ~= 7)
-- 与 或 非
print(true and false)
print(false or 1 == 1)
print(not (8 == 9))
--支持短路
print(true and print(123))
1.5 条件语句
a = 9
if a > 5 then
print(123)
elseif a < 3 then
print(321)
else
print("哈哈哈")
end
1.6 循环语句
num = 0
--while语句
while num < 5 do
print(num)
num = num + 1
end
print("----------------")
--do while语句
num = 0
repeat
print(num)
num = num + 1
until num > 5 --满足条件跳出
print("----------------")
--for 循环
num = 0
for i = 1,5 do --i会默认的递增
print(i)
end
print("----------------")
--自定义i递增幅度
for i = 1,10,2 do
print(i)
end
1.7 函数
--函数的第一种写法
function f1()
end
--第二种写法
f2 = function ()
end
-- 有参数的函数
function f2( a )
print(a)
end
f2("hhh")
f2("saklj",1,3)
f2()
-- 有返回值函数(多返回值)
function f4( a )
return a,"123",true
end
t1,t2,t3 = f4("asldkj")
print(t1)
print(t2)
print(t3)
--函数的类型
f4 = function ( )
end
print(type(f4))
--函数重载:不支持重载,会调用最后声明的函数
function f5( )
print("无参")
end
function f5( str )
print(str)
end
f5()
--变长参数
function f6( ... )
arg = {...}
for i = 1,#arg do
print(arg[i])
end
end
f6(1,"hh",true,'h',nil)
--函数嵌套
function f7( )
f8 = function( )
print("函数嵌套")
end
return f8
end
f9 = f7()
f9()
f7()()
-- 函数闭包
function f11( x )
return function( y )
return x + y
end
end
res = f11(10)(5)
print(res)
1.8 数组
print("---------数组----------")
--所有负载类型都是table
a = {1,"hh",true,nil,5,6,7}
-- lua的数组下标从1开始!!!
print(a[4])
--获取数组长度
print(#a)
print("---------数组遍历----------")
for i=1,#a do
print(a[i])
end
print("---------二维数组----------")
a = {{1,2,3},{4,5,6}}
print(a[1][1])
print("---------二维数组遍历----------")
for i=1,#a do
b = a[i]
for j=1,#b do
print(a[i][j])
end
end
print("---------自定义索引----------")
aa = {[0] = 1,[-1] = 2,3}
print(aa[-1])
print(aa[1])
--跳过一个索引,会默认为空
bb = {[1] = 1,[2] = 2,[4] = 4,[6] = 6}
print(#bb)
--跳过两个索引,就会停止遍历
bb = {[1] = 1,[4] = 4}
print(#bb)
1.9 迭代器
print("---------迭代器遍历----------")
a = {[0] = 1,2,[-1] = 3,4,5}
-- ipairs:只能从1开始找到连续索引的键,如果中间断续了,后续无法遍历
-- 通过索引遍历
for i,k in ipairs(a) do
print("ipairsb遍历键值"..i.."_"..k)
end
-- pairs迭代器:找到所有值
-- 遍历所有值
for i,j in pairs(a) do
print("pairs遍历键值"..i.."_"..j)
end
1.10 字典,类,对象
print("---------字典----------")
a = {["name"] = "shawn",["age"] = 14}
print(a["name"])
print(a.age)
a.age = 18
print(a["age"])
a.sex = false
print(a.sex)
a.sex = nil
print(a["sex"])
print("---------类和结构体----------")
-- lua中没有面向对象,需要自己前去实现
Student = {
age = 19,
sex = true,
Up = function ( )
Student.age = Student.age + 1
print("我成长了")
end,
Learn = function ( t )
print(t.sex)
print("好好学习")
end
}
Student.name = "shawn"
Student.Speak = function ( )
print("肖恩说话")
end
function Student.Haha( )
print("haha")
end
print(Student.age)
Student.Up()
Student.Speak()
Student.Haha()
print(Student.age)
print(Student["name"])
--Lua中.和:的区别
Student.Learn(Student)
Student:Learn()
print("---------表的公共操作----------")
t1 = {{age = 1,name = "123"},
{age = 2,name = "345"}}
t2 = {name = "Shawn",sex = true}
-- 表的插入
print(#t1) -- 2
table.insert(t1,t2)
print(#t1) -- 3
print(t1[3].name) -- Shawn
-- 删除指定元素
table.remove(t1)
print(t1[1].name) --123,移除最后一个元素
table.remove(t1,1)
print(t1[1].name) --456,移除指定索引内容
-- 列表排序
print("升序排列")
t2 = {5,2,4,7,9}
table.sort(t2)
for i,v in pairs(t2) do
print(i .. "_" .. v) --升序排列
end
--自定义排序
print("自定义排序")
table.sort(t2,function ( a,b )
if a > b then
return true
end
end)
for i,v in pairs(t2) do
print(i .. "_" .. v) --升序排列
end
--拼接
print("拼接")
tb = {"123","456","789"}
str = table.concat(tb,"_") --123_456_789
print(str)
1.11 多脚本执行
print("----多脚本执行----")
print("----全局变量与局部变量----")
--全局变量
--平时的的定义基本都是全局变量
--局部变量(尽量多使用local,否则浪费内存)
for i = 1,2 do
local d = "唐老师"
end
print(d)
print("----多脚本执行----")
--require关键字,使用其他脚本中的字段
require("Test")
print(A)
print(B) --因为是局部变量,没获取到
require("Test") --如果已经加载过,不会再执行
print("----脚本卸载----")
--package关键字
z = package.loaded["Test"] --得到是否被加载过
print(z)
package.loaded["Test"] = nil --卸载脚本
print(package.loaded["Test"])
print("----大G表----")
--_G是一个总表(table),他存储着我们申明的所有全局变量。
for k,v in pairs(_G) do
print(k , v)
end--
--将局部变量通过return返回出去,可以在外部访问变量
package.loaded["Test"] = nil
local locolB = require("Test")
print(localB)
1.12 特殊语法
-- and 和 or逻辑
--不仅可以连接boolean,任何东西都可以连接。
--在lua中,只有nil和false被认为是假
print(1 and 2) --2
print(0 and 1) --1
print(nil and 1) -- nil
print(false and 2) -- false
print(true and 3) --3
print(true or 1) --true
print(false or 2) --2
print(nil or 3) -- 3
1.13 协程
print("协程的创建")
--coroutine.create()
fun = function ( )
print(123)
end
co = coroutine.create(fun)
print(co) --thread...协程本质是线程对象
--coroutine.wrap()
co2 = coroutine.wrap(fun)
print(co2) --返回一个函数function
print("协程的运行")
--第一种
coroutine.resume(co)
--第二种
co2()
print("协程的挂起")
func2 = function ( )
local i = 1
while true do
print(i)
i = i + 1
--协程的挂起
coroutine.yield()
end
end
--1
co3 = coroutine.create(func2)
coroutine.resume(co3)
coroutine.resume(co3)
coroutine.resume(co3)
--默认第一个参数是有无启动成功,第二参数是真返回值
--2
co4 = coroutine.wrap(func2)
co4()
co4()
co4()
--没有默认第一个是否执行成功的返回值
print("协程的状态")
--coroutine.status(协程对象)
print(coroutine.status(co3)) --暂停
print(coroutine.status(co))
1.14 元表
print("-------元表概念------")
--任何表变量都可以作为其他的元表
--在对子表中进行一些特定操作时,会执行元表的内容
print("-------元表设置------")
meta = {}
myTable = {}
--Param:子表,元表
setmetatable(myTable,meta)
print("-------特定操作tostring------")
meta2 = {
__tostring = function ( t )
return t.name
end,
--当子表被当作一个函数来使用时,会默认调用call
--当希望传参数时,默认第一个参数是调用者自己
__call = function ( a,b )
print(a ," " , b)
end
}
mytable2 = {
name = "Shawnlove"
}
setmetatable(mytable2,meta2);
print(mytable2) --Shawn(获得了元表中的函数数据)
--当子表被当作一个函数来使用时,会默认调用call
mytable2(100) --Shawnlove 100
print("-------特定操作call------")
meta4 = {
__add = function ( t1,t2 )
return t1.age + t2.age
end
--sub,mul,div,mod,pow,eq,lt,le,concat
}
mytable4 = {age = 1}
mytable5 = {age = 20}
setmetatable(mytable4,meta4)
print(mytable4 + mytable5) -- 21
print("-------特定操作 运算符重载------")
print("-------特定操作 index和newIndex------")
meta6 = {age = 1}
meta6.__index = meta6 --__index写在外面取赋值
mytable6 = {}
setmetatable(mytable6,meta6)
--当子表中找不到某个属性时,会到元表中__index指向的索引
print(mytable6.age);
--newIndex
meta7 = {}
meta7.__newIndex = {}
mytable7 = {}
setmetatable(mytable7,meta7)
mytable7.age = 100
print(mytable7.age)
1.15 面向对象
print("封装")
Object = {}
Object.id = 99
function Object:new()
local obj = {}
self.__index = self --当找自己找不到时,会顺着元表中index指向的内容
setmetatable(obj,self)
return obj
end
function Object:Test( )
print(self.id)
end
local myObj = Object:new()
print(myObj)
print(myObj.id) --1
myObj:Test()
--修改id仅修改了当前对象的id
myObj.id = 2
myObj:Test() --2
print("继承")
--C#: class 类名 : 父类
--写一个用于继承的函数
function Object:subClass( className )
--_G:本质是一个总表,所有声明的全局变量都存在其中
_G[className] = {}
--元表
local obj = _G[className]
self.__index = self
obj.base = self
setmetatable(obj,self)
end
Object:subClass("Person")
print(Person.id)
print("多态")
--相同方法,不同具体表现,就是多态
Object:subClass("GameObject")
GameObject.x = 0
GameObject.y = 0
function GameObject:Move( )
self.x = self.x + 1
self.y = self.y + 1
print(self.x)
print(self.y)
end
GameObject:subClass("Player")
function Player:Move( )
self.base.Move(self)
end
local p1 = Player:new()
p1:Move()
p1:Move()
local p2 = Player:new()
p2:Move()
1.16 库函数
--时间相关
print("---时间相关")
--系统时间
print(os.time())
print(os.time({year = 2022,month = 12,day = 19}))
local nowTime = os.date("*t")
for k,v in pairs(nowTime) do
print(k,v)
end
print(nowTime.sec)
print("---数学运算")
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,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(100))
print("---路径")
--加载路径
print(package.path)
--垃圾回收关键字
test = {id = 1,name = "haha"}
--获取当前lua占用内存数K字节,用返回值*1024就可以得到具体内存占用字节数
print(collectgarbage("count"))
test = nil
collectgarbage("collect")
print(collectgarbage("count"))
--Unity中尽量手动进行垃圾回收