Lua热更新

Lua热更新解决方案

文章目录

  • Lua热更新解决方案
    • 1.AB包
      • 1.1 AB包概述
    • 2. 从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 库函数
    • 3.xlua热更解决方案
      • 3.1 准备工作
      • 3.2 Lua解析器

1.AB包

1.1 AB包概述

AB包:特定于平台的资产压缩包,类似压缩文件,资产包括 模型,贴图,预设体,音效,材质球等。

Resources和AB包的区别
Resources打包时为只读,无法修改。
AB包存储位置和压缩方式可自定义,后期可以动态更新。
AB包可以减小包体大小,并且实现资源或者脚本的热更新。

热更新的基本规则
Lua热更新_第1张图片
Tip:C#脚本无法打成AB包,这也是我们学习Lua的原因。Lua热更新_第2张图片

ABBrowser参数相关 : build页面:

Lua热更新_第3张图片

2. 从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中尽量手动进行垃圾回收

3.xlua热更解决方案

3.1 准备工作

导入xLua资源:github
导入AB包资源

3.2 Lua解析器

你可能感兴趣的:(游戏与梦想,lua,开发语言)