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
    }
);

 

posted @ 2023-05-19 15:29  CatSevenMillion  阅读(198)  评论(0)    收藏  举报