Unity:lua热更新(一)——AB包AssetBundle、Lua语法

写在前面:

写本系列**(自用)**的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解,方便自己以后快速复习,减少遗忘。主要是C#代码部分。

一、AB包AssetBundle

1、创建AB包

导入AssetBundle资源后,选中资源区中的预设体,在右侧inspector窗口下方AssetBundle处点击下拉列表选择new,创建一个新AB包并为其取名即可。这里AB包命名为model。

创建完成后,点击Window,并选择AssetBundle Browser即可查看当前工程中的AB包。

点击Build页签,黄色框中框选的即为主包路径,可以将名字修改一下,例如修改为PC(不改也行,改短了方便使用)。

如果想要一键将多个物体打包在同一个AB包里,按下shift或者ctrl进行选择即可。

2、加载AB包中的资源

(1)同步加载

想要加载AB包中的资源,需要先加载AB包。

加载AB包使用的api是AssetBundle.LoadFromFile(),括号内传入AB包路径。AB包会被保存在streamingAssets文件夹中,因此路径为Application.streamingAssetsPath + "/" + "你为AB包取的名字"

加载AB包后就可以加载AB包的资源。可以直接调用api用资源的名字加载,如我想要加载上一步中打包在model包中的Cube:ab.LoadAsset("Cube");

cs 复制代码
void Start()
{
    AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "model");

    ab.LoadAsset("Cube");
}

但只用名字加载时,如果出现同名不同类型的资源,会分不清。因此,建议泛型加载或是Type指定类型。泛型加载为GameObject obj = ab.LoadAsset<GameObject>("Cube");

类型加载为GameObject obj = ab.LoadAsset("Cube", typeof(GameObject)) as GameObject;

cs 复制代码
void Start()
{
    AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "model");
   
    GameObject obj = ab.LoadAsset<GameObject>("Cube");

    //GameObject obj = ab.LoadAsset("Cube", typeof(GameObject)) as GameObject;

    Instantiate(obj);
}

(2)异步加载

除了同步加载外,还可以使用异步加载,防止玩家游玩时游戏卡顿。异步加载涉及到协程的知识。可以启动协程,配合异步加载apiAssetBundle.LoadFromFileAsync()来进行加载,括号内传入的是需要加载资源的路径。

加载得到的AB包类型为AssetBundleCreateRequest,记住即可。加载完AB包后,加载AB包中的资源,对应的API为.assetBundle.LoadAssetAsync(),括号内传入两个参数,资源名字与资源类型。返回类型为AssetBundleRequest。

得到资源后,可以.asset得到加载的资源。由于该类型默认为object,还需要将资源类型转化为你想要加载的资源的类型。

cs 复制代码
public Image image;

void Start()
{
    StartCoroutine(LoadABRes("head", "23_11100001"));
}

IEnumerator LoadABRes(string ABName, string resName)
{
    AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + ABName);
    yield return abcr;
    AssetBundleRequest abq = abcr.assetBundle.LoadAssetAsync(resName, typeof(Sprite));
    yield return abq;
    image.sprite = abq.asset as Sprite;
}

3、AB包的卸载

AB包是不能重复加载的,如果重复加载了,哪怕和原来加载的ab包名字不同也会报错,比如如下的代码是会报错的:

cs 复制代码
void Start()
{
    AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "model");

    AssetBundle ab2 = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "model");
}

卸载AB包也有专门的API。

AssetBundle.UnloadAllAssetBundles(),可以直接卸载所有加载的AB包,括号内传入bool参数,如果是true,会将场景上所有从ab包内加载的资源删除,例如前面已经实例化了的cube。因此一般填false。

也可以卸载单个AB包:ab.Unload(),括号内参数同理。

cs 复制代码
void Start()
{
    //加载AB包
    AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "model");

    AssetBundle.UnloadAllAssetBundles(false);

    ab.Unload(false);
}

4、AB包依赖

AB包依赖说的是,一个资源身上用到了别的AB包中的资源,这个时候如果只加载自己的AB包,会出现资源丢失的情况这。种时候,需要把依赖包一起加载了。

依赖包的关键知识点是------利用主包 获取依赖信息。主要有如下几个步骤:

1、加载主包:AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "PC");这里的"PC"是我们一开始为主包改的名。

2、加载主包中的固定文件: AssetBundleManifest abMainfest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");这句代码基本是固定的,固定文件的类型、名字等都是Unity内部固定的,记住即可。

3、从固定文件中 得到依赖信息。使用string[] strs = abMainfest.GetAllDependencies("model");,就可以得到model的所有依赖信息了,之后遍历这些依赖信息,把所有相关的AB包加载了即可。

cs 复制代码
void Start()
{
    AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "PC");

    AssetBundleManifest abMainfest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

    string[] strs = abMainfest.GetAllDependencies("model");
    for(int i = 0; i < strs.Length; i++)
    {
        AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + strs[i]);
    }
}

二、Lua语法

1、lua注释及第一个lua程序

lua可以单行注释、多行注释。多行注释有三种方式。

(1)单行注释

使用--双横杠即可

Lua 复制代码
--单行注释

(2)多行注释

如下,有三种方式,都大同小异。

Lua 复制代码
--[[
多行注释
]]
--[[
第二种
]]--
--[[
第三种
--]]

(3)第一个lua程序

lua使用print打印函数,与C#不同,lua语句可以省略分号:

Lua 复制代码
print("hello world")

2、变量

(1)简单变量类型

有nil number string boolean

需要说明的是:lua里面的所有变量声明都不需要声明变量类型,他会自动判断类型。也就是说lua中的一个变量,可以随便赋值。a = 1, a = 1.4, a = true。

通过type函数可以得到变量类型,返回值是string。

①nil

nil 类似于C#里的null,lua中使用没有声明过的变量 不会报错 默认值是nil。

Lua 复制代码
print("************变量************")

print(b)
Lua 复制代码
print("************nil************")
a = nil
print(a)
print(type(a))
print(type(type(a)))
②number

在lua中,所有的数值都是number,不分int float之类的。

Lua 复制代码
print("************number************")
a = 1
print(a)
print(type(a))
a = 1.2
print(a)
print(type(a))
③string

string是字符串类型,可以用单引号或者双引号包裹,因为lua里没有char,无论如何都是string。

Lua 复制代码
print("************string************")
a = "2345"
print(a)
a = '123'
print(a)
print(type(a))
④boolean

相当于C#的bool类型

Lua 复制代码
print("************boolean************")
a = true
print(a)
a = false
print(a)
print(type(a))

(2)复杂数据类型

复杂数据类型主要包括:函数 function、表 table、数据结构 userdata、协同程序 thread(线程)。会在后续介绍。

3、string

无论是单引号还是双引号,都是字符串

Lua 复制代码
print("************字符串************")
str = "双引号字符串"
str2 = '单引号字符串'

(1)获取字符串长度

可以使用#来获取,例如想要获取字符串s的长度,打印#s即可。

需要注意的是,一个汉字占三个长度,一个英文字符占一个长度,如下

Lua 复制代码
print("************字符串长度************")

s = "aBcdEfg"
print(#s)

s = "字符串"
print(#s)

(2)字符串多行打印

lua也支持转义字符,所以可以在字符串中插入\n来进行多行打印。

也可以使用两个中括号进行多行打印,如下

Lua 复制代码
print("************字符串多行打印************")
print("123\n123")

s = [[南瓜
牛乳小丸子
好好吃
]]
print(s)

(3)字符串拼接

可以通过两个点拼接 "123" .. "456"

也可以通过string.format(),该用法与C语言类似。%d表示数字,%a表示字母,%s表示字符。

Lua 复制代码
print("************字符串拼接************")

print("123" .. "456")
s1 = "1234"
s2 = 111
print(s1 .. s2)

print(string.format("我今年%d岁了", 18))

(4)别的类型转字符串

使用lua提供的tostring()函数即可,括号内传入希望转为字符串的变量

Lua 复制代码
print("************别的类型转字符串************")
a = true
print(tostring(a))

(5)字符串提供的公共方法

1、小写转大写与大写转小写

需要注意的是,这一系列公共方法,会得到新字符串不会改原来的字符串。

小写转大写的方法:string.upper()

大写转小写:string.lower()

Lua 复制代码
print("************字符串提供的公共方法************")
str = "abCdefg"

print(string.upper(str)) 
print(str)

print(string.lower(str))

2、翻转字符串

使用api:string.reverse()

Lua 复制代码
print(string.reverse(str))

3、字符串索引查找

使用string.find(str, "Cde")),第一个参数是要进行查找的字符串,第二个参数是要查找的内容

该函数,会返回开始位置和结束位置。值得注意的是,lua的字符串索引是从1开始的

Lua 复制代码
print(string.find(str, "Cde"))

4、截取字符串

使用string.sub(),第一个参数传入的是需要进行截取的字符串。接下来,

如果只传一个数字:从该数字到结尾都截取返回

如果传两个数字:那么就会返回这两个数字之间的字符

Lua 复制代码
print(string.sub(str, 3))

print(string.sub(str, 3, 4))

5、字符串重复与字符串修改

字符串重复使用string.rep(),参数一是重复的字符串,参数二是重复的次数

字符串修改string.gsub(),参数一传入字符串,参数二是需要修改的字符,参数三是需要修改为什么。例如string.gsub(str, "Cd", "**")指的是,把字符串str中的Cd都改为*。返回值会多出一个数字,得到的数字指的是修改了几次,例如如果str中有两个Cd,就会返回2。

Lua 复制代码
print(string.rep(str, 2))

print(string.gsub(str, "Cd", "**"))

6、字符 ASCII码 互转

string.byte(),第一个参数是字符串,第二个参数是需要转换的索引。例如string.byte("Lua", 1)指的是把Lua字符串的第一个字符L转为ASCII码。

string.char(),ASCII码转字符串

Lua 复制代码
a = string.byte("Lua", 1)
print(a)

print(string.char(a))

4、运算符

(1)算数运算符

主要包括+ - * / % ^,没有 自增自减 ++ --(使用会报错),没有复合运算符 += -= *= /=(使用会报错)。

    • * / % ^分别是加、减、乘、除、取余、幂。

非常特殊的一点是,只要字符串能转为数字,都可以直接和数字进行加减乘除运算。如下:

print("123.4" + 1)也是能正常运算的

Lua 复制代码
print("************运算符************")
print("************算数运算符************")

print("加法运算" .. 1 + 2)
a = 1
b = 2
print(a + b)

print("123.4" + 1)

其他的运算也同理:

Lua 复制代码
print("减法运算" .. 1 - 2)
print("123.4" - 1)

print("乘法运算" .. 1 * 2)
print("123.4" * 1)

print("除法运算" .. 1 / 2)
print("123.4" / 1)

print("取余运算" .. 1 % 2)
print("123.4" % 1)

--lua中是幂运算,c#是位运算
print("幂运算" .. 1 ^ 2)
print("123.4" ^ 1)

(2)条件运算符

> < >= <= == ~=:大于,小于,大于等于,小于等于,等于等于,不等于。

注意这里不等于使用的是~=,C#里使用的是!=

Lua 复制代码
print("************条件运算符************")
print(3>1)
print(3<1)
print(3>=1)
print(3<=1)
print(3==1)
print(3~=1)

(3)逻辑运算符

与或非,使用的是and、or、not 。也遵循"短路"原则。

短路说的是print(false and print("123")),这句代码,由于and的左侧是false,那么这个条件就一定是false的,and不会再执行右侧的语句。

反之print(true and print("123"))就会有打印输出。

Lua 复制代码
print("************逻辑运算符************")

print(true and false)
print(true and true)
print(true or false)
print(false or false)
print(not true)

print(false and print("123"))
--print(true and print("123"))

(4)位运算符与三目运算符

lua不支持位运算符,需要我们自己实现;lua也不支持三目运算符。

相关推荐
霜绛2 小时前
Unity:lua热更新(二)——Lua语法(续)
笔记·学习·unity·游戏引擎·lua
yi碗汤园3 小时前
【一文了解】C#反射
开发语言·unity·c#
py有趣3 小时前
LeetCode算法学习之数组中的第K个最大元素
学习·算法·leetcode
YangYang9YangYan3 小时前
职业本科发展路径与规划指南
大数据·人工智能·学习·数据分析
xiaoyans5283 小时前
steam安装游戏为什么磁盘写入错误?磁盘写入错误怎么办?,同样问题解决方案
游戏
HahaGiver6664 小时前
Unity Shader Graph 3D 实例 - 基础的模型贴图渲染
3d·unity·游戏程序·贴图·游戏美术
HahaGiver6664 小时前
Unity Shader Graph 3D 实例 - 一个简单的3D打印效果
3d·unity·游戏引擎
YuforiaCode4 小时前
黑马Python+AI大模型开发课程笔记(个人记录、仅供参考)
笔记
lkbhua莱克瓦244 小时前
Java练习——数组练习
java·开发语言·笔记·github·学习方法