AB包是特定于平台的资产压缩包,类似于压缩文件
相对于RESOURCES下的资源,AB包更加灵活轻量化,用于减小包体大小和热更新
可以在unity2019环境中直接下载Asset Bundle Browser


可以在其中设置关联

AB包文件:资源文件
manifest文件:AB包文件信息;当加载时,提供了关键信息,资源信息,依赖关系,版本信息等等
关键AB包(和目录名一样的包 )
- void Start(){
- //加载AB包
- AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath+"/"+"model");
-
- //加载AB包中的资源
- //只用名字加载那么会出现同名同类型资源混乱
- GameObject obj = ab.LoadAsset
("Cube"); -
- }
关于AB包的依赖一一个资源身 上用到了别的AB包中的资源这个时候如果只加载自己的AB包,通过它创建对象会出现资源丢失的情况,这种时候需要把依赖包-起加载了才能正常
可以考虑利用主包获取信息
- //加载AB包
- AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath+"/"+"model");
-
- //加载主包和其中的固定文件
- AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath +"/"+"PC");
- AssetBundleManifest abManifest=abMain.LoadAsset
("AssetBundleManifest");
- public class ABMgr : SingletonAutoMono<ABMgr>
- {
- //主包
- private AssetBundle mainAB = null;
- //主包依赖获取配置文件
- private AssetBundleManifest manifest = null;
-
- //选择存储 AB包的容器
- //AB包不能够重复加载 否则会报错
- //字典知识 用来存储 AB包对象
- private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();
-
-
- private string PathUrl
- {
- get
- {
- return Application.streamingAssetsPath + "/";
- }
- }
-
-
- private string MainName
- {
- get
- {
- #if UNITY_IOS
- return "IOS";
- #elif UNITY_ANDROID
- return "Android";
- #else
- return "PC";
- #endif
- }
- }
-
-
- private void LoadMainAB()
- {
- if( mainAB == null )
- {
- mainAB = AssetBundle.LoadFromFile( PathUrl + MainName);
- manifest = mainAB.LoadAsset
("AssetBundleManifest"); - }
- }
-
-
- private void LoadDependencies(string abName)
- {
- //加载主包
- LoadMainAB();
- //获取依赖包
- string[] strs = manifest.GetAllDependencies(abName);
- for (int i = 0; i < strs.Length; i++)
- {
- if (!abDic.ContainsKey(strs[i]))
- {
- AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);
- abDic.Add(strs[i], ab);
- }
- }
- }
-
-
- public T LoadRes<T>(string abName, string resName) where T:Object
- {
- //加载依赖包
- LoadDependencies(abName);
- //加载目标包
- if ( !abDic.ContainsKey(abName) )
- {
- AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
- abDic.Add(abName, ab);
- }
-
- //得到加载出来的资源
- T obj = abDic[abName].LoadAsset
(resName); - //如果是GameObject 因为GameObject 100%都是需要实例化的
- //所以我们直接实例化
- if (obj is GameObject)
- return Instantiate(obj);
- else
- return obj;
- }
-
-
- public Object LoadRes(string abName, string resName, System.Type type)
- {
- //加载依赖包
- LoadDependencies(abName);
- //加载目标包
- if (!abDic.ContainsKey(abName))
- {
- AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
- abDic.Add(abName, ab);
- }
-
- //得到加载出来的资源
- Object obj = abDic[abName].LoadAsset(resName, type);
- //如果是GameObject 因为GameObject 100%都是需要实例化的
- //所以我们直接实例化
- if (obj is GameObject)
- return Instantiate(obj);
- else
- return obj;
- }
-
- public Object LoadRes(string abName, string resName)
- {
- //加载依赖包
- LoadDependencies(abName);
- //加载目标包
- if (!abDic.ContainsKey(abName))
- {
- AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
- abDic.Add(abName, ab);
- }
-
- //得到加载出来的资源
- Object obj = abDic[abName].LoadAsset(resName);
- //如果是GameObject 因为GameObject 100%都是需要实例化的
- //所以我们直接实例化
- if (obj is GameObject)
- return Instantiate(obj);
- else
- return obj;
- }
-
-
- public void LoadResAsync<T>(string abName, string resName, UnityAction
callBack ) where T:Object - {
- StartCoroutine(ReallyLoadResAsync
(abName, resName, callBack)); - }
- //正儿八经的 协程函数
- private IEnumerator ReallyLoadResAsync<T>(string abName, string resName, UnityAction
callBack ) where T : Object - {
- //加载依赖包
- LoadDependencies(abName);
- //加载目标包
- if (!abDic.ContainsKey(abName))
- {
- AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
- abDic.Add(abName, ab);
- }
- //异步加载包中资源
- AssetBundleRequest abq = abDic[abName].LoadAssetAsync
(resName); - yield return abq;
-
- if (abq.asset is GameObject)
- callBack(Instantiate(abq.asset) as T);
- else
- callBack(abq.asset as T);
- }
-
-
- public void LoadResAsync(string abName, string resName, System.Type type, UnityAction)
- {
- StartCoroutine(ReallyLoadResAsync(abName, resName, type, callBack));
- }
-
- private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction)
- {
- //加载依赖包
- LoadDependencies(abName);
- //加载目标包
- if (!abDic.ContainsKey(abName))
- {
- AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
- abDic.Add(abName, ab);
- }
- //异步加载包中资源
- AssetBundleRequest abq = abDic[abName].LoadAssetAsync(resName, type);
- yield return abq;
-
- if (abq.asset is GameObject)
- callBack(Instantiate(abq.asset));
- else
- callBack(abq.asset);
- }
-
-
- public void LoadResAsync(string abName, string resName, UnityAction)
- {
- StartCoroutine(ReallyLoadResAsync(abName, resName, callBack));
- }
-
- private IEnumerator ReallyLoadResAsync(string abName, string resName, UnityAction)
- {
- //加载依赖包
- LoadDependencies(abName);
- //加载目标包
- if (!abDic.ContainsKey(abName))
- {
- AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
- abDic.Add(abName, ab);
- }
- //异步加载包中资源
- AssetBundleRequest abq = abDic[abName].LoadAssetAsync(resName);
- yield return abq;
-
- if (abq.asset is GameObject)
- callBack(Instantiate(abq.asset));
- else
- callBack(abq.asset);
- }
-
- //卸载AB包的方法
- public void UnLoadAB(string name)
- {
- if( abDic.ContainsKey(name) )
- {
- abDic[name].Unload(false);
- abDic.Remove(name);
- }
- }
-
- //清空AB包的方法
- public void ClearAB()
- {
- AssetBundle.UnloadAllAssetBundles(false);
- abDic.Clear();
- //卸载主包
- mainAB = null;
- }
- }
第一个lua程序
- print("你好世界");
- --单行注释
- --lua语句可以省略分号
-
-
- --[[
- 多行数据
- ]]
-
-
- --[[
- 多行数据
- ]]--
-
- --[[
- 还是多行数据
- --]]
lua的变量(lua中所有的变量声明都不需要申明类型,会自动的判断类型)
简单变量类型:nil number string boolean
nil 相当于空的概念
number 所有的数值都是number(lua中的一个变量可以随便赋值)
string 字符串类型,字符串的声明需要用单双引号包裹,lua中无char类型
boolean 真或假
可以通过type获得变量类型,其返回值是string类型
注意:lua中使用没有声明过的变量不会报错,其值是空
其他数据类型:function table userdata thread
字符串操作
- s="5464565655"
-
- print(#s)
- --获取字符串长度
- --中文字符在lua中占三个长度
- --多行打印
- --lua中支持转义字符
- print("123\n123")
-
- s =[[hello
- world
- ]]
- --字符串拼接
- print("1323".."65456")
注意lua字符串索引开始都是从1开始的,而不是从0开始
运算符
算术运算符:+-*/%^
与c#中基本相同,但是需要注意lua中无++ -- += *= %= -=
(字符串可以进行算数运算符的惭怍 会自动转成number)
lua中^是幂运算
条件运算符:> < <= == ~=
~= Lua中的不等于 相当于C#中的!=
逻辑运算符
&& || (c#)
and or (lua)
not 取反
lua中and和or支持短路原则
位运算符(不支持)
三目运算符(不支持)
条件分支语句
- print("条件分支语句")
-
- -- if 条件 then ... end
- if a > 6 then
-
- print("666")
- elseif a == 999 then
- print("123")
- else
- print("555")
- end
在lua中没有switch语句
循环语句
- num = 0
- --while
- while num <555 do
- print(num)
- num =num +1
- end
-
- --do while
- repeat
- print(num)
- until num>555
- --满足条件跳出,不同于C#中的进入条件
-
- --for语句
- for i =1,5 do
- print(i)
- end
- for i =1,5,2 do
- print(i)
- end
函数
function 函数名()
end
不同于c#,函数在声明之前,不能调用
无参无返回值
- F2 = function()
- print("F1hanshu")
- end
- F2()
有参有返回值
- F2 = function(a)
- print(a)
- end
- F2(1)
- F2()
- --不传参数,默认为空
如果传入的参数和函数参数个数不匹配,不会报错,只会补nil或者丢弃参数
- F2 = function(a)
- return a ,"123",false
- end
- tt = F2(a)
多返回值时,在前面申明多个变量来截取,变量不够会接取对应位置的返回值
函数的类型
- F2 = function()
- print("F1hanshu")
- end
- F2()
- print(type(F2))
函数的重载
LUA中不支持函数的重载
变长参数
- F2 = function(...)
- print("F1hanshu")
- end
- F2()
变长参数使用 先用一个表存起来 再来使用
函数嵌套
- F2 = function()
- F6 =function()
- print(666);
- end
- return F9
- print("F1hanshu")
- end
-
- f9 =F2()
- f9()
table表实现数组
所有的复杂类型本质上都是Table
数组:
- a ={1,2,3,true,nil,"9916"}
- print(a[1])
- --lua中的索引从1开始
获取数组长度
- --#是通用的获取长度的关键字
- --在打印长度时,nil和其数组后面的数据将会被省略
自定义索引:
- aa ={[0]=1,2,3,[-5]=4,5}
- print(aa[-5])
- print(#aa)
- --输出为4 3
迭代器遍历
主要是用于遍历表
#得到的长度,其实是不准确的 一般不会使用#来遍历表
- aa ={[0]=1,2,3,[-5]=4,5}
- --ipairs
- for i ,k in ipairs(aa) do
- print(i..k)
- end
-
ipairs遍历还是从1开始遍历,小于等于0的值得不到,只能找到连续连续索引的键值
- aa ={[0]=1,2,3,[-5]=4,5}
- --pairs
- for i ,v in pairs(aa) do
- print(i..v)
- end
- --能把所有键都找到 通过键找到值
table表现字典
- --字典的声明
- a = {["name"]="Name",["anme"]=5}
- print(a["name"])
- --还可以类似.成员变量的形式得到值,但是不能是数字
- print(a.name)
-
- --字典新增
- a["newnew"]=666
-
- --模拟字典 遍历一定要使用pairs
- for k,v in pairs(a) do
- --可以穿多个参数 一样可以打印出来
- print(k,v)
- end
-
- for _,v in pairs(a) do
- --遍历值
- print(v)
- end
table实现类
lua中默认没有面向对象,需要自己去实现
- Student ={
- age =1,
- sex=true,
- Up=function function_name( )
- -- body
- print("函数")
- end
-
- }
-
- print(Student.age)
- Student.Up()
lua中.和:的区别在于,:调用方法时,会默认把调用者作为第一个参数传入方法中
表的公共操作
- a = {{age =1 ,name ="123"},{age =2 ,name="456"}}
- b={name ="54645",sex=false}
-
- --插入
- table.insert(a,b);
- --在a表中加入b
-
- --删除指定元素
- --移除最后一个索引的内容
- table.remove(a)
-
- --排序算法
- t={5,9,54,5,7}
- table.sort(t)
多脚本执行
全局变量与本地变量
- --全局变量与本地变量
- a = 1
- b = 1
- --以上都是全局变量
-
- for i=1,2 do
- c=1
- end
-
- --c还是全局变量
-
- --本地变量的关键字是 local
- fun =function()
- tt="123123"
- end
- fun()
- print(tt)--能正常输出,是全局变量
多脚本执行
全局变量,只要执行过后,可以在任何脚本中进行调用
脚本卸载
如果是require("")加载执行的脚本,加载一次过后不会再执行
可以利用package.loaded["脚本名"]来判断脚本是否被执行
大G表
是一个总表,将我们声明的全部全局变量都储存在其中,本地变量不会存储
LUA的特殊用法
多变量赋值
- l,g,c = 1 ,2 ,true
- l,g,c=1,2
- --多变量赋值后面的值不够会自动补空,多了会自动省略
多返回值
- function Test()
- return 10,20,30
- end
- a,b,c =Test()
and 与 or
在lua中只有 nil 和 false才会被认为是假
lua模拟三目运算符
local res = (x>y) and x or b
协同程序
- --coroutine.create()
- fun = function()
- print(123)
- end
- --协程本质上是一个线程对象
- lu=coroutine.create(fun)
-
- --coroutine.wrap()
- ji = coroutine.wrap(fun)
-
-
- --协程运行
- coroutine.resume(lu)
- ji()
-
- --协程的挂起
- fun2=function()
- while true do
- print(123)
- --挂起函数
- coroutine.yield()
- end
- end
-
- peng =coroutine.create(fun2)
- coroutine.resume(peng)
元表
任何表对象都可以作为另一个表变量的元表
当对子表中进行特定操作时,会执行元表中的内容
- mega = {
- --当子表要被当作字符串使用时,会默认调用元表中的tostring方法
- __tostring =function(t)
- return t.name
- end,
- --当子表被当作一个函数使用时,会默认调用__call中的内容
- __call =function(a,b)
- print(a)
- print(b)
- --默认第一个参数是调用自己
- end
- }
- myMega = {
- name = "666"
- }
- --设置元表函数
- --第一个为子表,第二个为夫表
- setmetatable(myMega,mega)
-
- print(myMega)
LUA自带库
- --系统时间
- print(os.time())
- print(os.time({year=2014,month=8,day=14}))
-
-
- local nowTime =os.data("*t")
- --可以得到更多的信息
-
- --数学运算
- print(math.abs(-1555))
-
- --弧度转角度
- print(math.deg(math.pi))
-
- --向下取整
- print(math.floor(-1555))
-
- --最小值
- print(math.min(-1555,999))
-
- --小数分离
- print(math.modf(1.5555))
-
-
- --随机数
- math.randomseed(os.time())
- print(math.random(100))
-
-
- --路径
- print(package.path)
- --打印LUA脚本加载路径
垃圾回收
- --垃圾回收
- lu={id=1,idd=2}
- collectgarbage("count")
- --获取当前lua占用内存数,返回千字节单位
-
- --进行垃圾回收
- collectgarbage("collect")
- print(collectgarbage("count"))--lua的垃圾回收机制和c#中类似,取消羁绊便成为垃圾
-
- --lua中有自动计时垃圾回收的方法,但不推荐在项目中使用