[unity]lua热更新——个人复习笔记【侵删/有不足之处欢迎斧正】

news2024/9/25 15:25:35

一、AssetBundle

AB包是特定于平台的资产压缩包,类似于压缩文件

相对于RESOURCES下的资源,AB包更加灵活轻量化,用于减小包体大小和热更新

可以在unity2019环境中直接下载Asset Bundle Browser

可以在其中设置关联

AB包生成的文件

AB包文件:资源文件
manifest文件:AB包文件信息;当加载时,提供了关键信息,资源信息,依赖关系,版本信息等等
关键AB包(和目录名一样的包 )

AB包资源加载

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

//加载AB包中的资源
//只用名字加载那么会出现同名同类型资源混乱
GameObject obj = ab.LoadAsset<GameObject>("Cube");

}

AB包依赖

关于AB包的依赖一一个资源身 上用到了别的AB包中的资源这个时候如果只加载自己的AB包,通过它创建对象会出现资源丢失的情况,这种时候需要把依赖包-起加载了才能正常

可以考虑利用主包获取信息

//加载AB包
AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath+"/"+"model");

//加载主包和其中的固定文件
AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath +"/"+"PC");
AssetBundleManifest abManifest=abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

AB包资源加载管理器

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>("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<T>(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<T> callBack) where T:Object
    {
        StartCoroutine(ReallyLoadResAsync<T>(abName, resName, callBack));
    }
    //正儿八经的 协程函数
    private IEnumerator ReallyLoadResAsync<T>(string abName, string resName, UnityAction<T> 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<T>(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<Object> callBack)
    {
        StartCoroutine(ReallyLoadResAsync(abName, resName, type, callBack));
    }

    private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
    {
        //加载依赖包
        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<Object> callBack)
    {
        StartCoroutine(ReallyLoadResAsync(abName, resName, callBack));
    }

    private IEnumerator ReallyLoadResAsync(string abName, string resName, UnityAction<Object> callBack)
    {
        //加载依赖包
        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基础语法

第一个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中有自动计时垃圾回收的方法,但不推荐在项目中使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1486649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

码垛工作站:食品生产企业的转型助推器

在当今高度自动化的工业生产中&#xff0c;码垛工作站的应用正逐渐成为一种趋势。某食品生产企业在面临市场竞争加剧、人工成本上升等多重压力下&#xff0c;决定引入码垛工作站&#xff0c;以期实现生产流程的升级与变革。 一、码垛工作站引入背景 该企业主要从事休闲食品的…

Github 2024-03-03 开源项目日报Top9

根据Github Trendings的统计&#xff0c;今日(2024-03-03统计)共有9个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量非开发语言项目4Rust项目1C项目1Jupyter Notebook项目1Python项目1Shell项目1 任天堂Switch模拟器yuzu&#x…

云计算市场,从追求“规模制胜”到走向“用户分化”

文|智能相对论 作者|叶远风 通常来说&#xff0c;价格战放到任何行业&#xff0c;都不是什么好事。 如今&#xff0c;作为曾经的前沿技术创新&#xff0c;云计算行业正在被迫走入价格战的阴霾当中&#xff0c;引发业界担忧。 ECS&#xff08;云服务器&#xff09;最高降36%…

559.n叉树的最大深度

这段代码是一个Java类Solution&#xff0c;其中包含一个公共方法maxDepth&#xff0c;用于计算一个二叉树的最大深度。这里的二叉树是一个特殊的数据结构&#xff0c;其中每个节点Node可能有一个或多个子节点&#xff08;在这里被称为children&#xff09;。下面是对代码的详细…

Manomotion 实现AR手势互动-解决手势无效的问题

之前就玩过 Manomotion &#xff0c;现在有新需求&#xff0c;重新接入发现不能用了&#xff0c;不管什么办法&#xff0c;都识别不了手势&#xff0c;我记得当初是直接调用就可以的。 经过研究发现&#xff0c;新版本SDK改了写法。下边就写一下新版本的调用&#xff0c;并且实…

FRM模型十四:FRA估值

什么是FRA FRA&#xff08;Forward rate agrreement&#xff09;远期利率协议&#xff0c;是一种场外衍生品。FRA在0时刻确定&#xff0c;在未来时刻进行交易的协议。例如FRA3,6表示双方约定在3个月后以Rk的利率水平借款3个月。 应用场景&#xff1a;某公司未来3个月有融资需…

政安晨【示例演绎虚拟世界开发】(六):从制作一个对战小游戏开始(Cocos Creator 《击败老大》)(第三段)

在上一篇文章中&#xff0c;我们已经将游戏的场景基本搭建完毕&#xff0c;接下来我们就可以为游戏编写代码并实现相关的核心逻辑了。 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: AI虚拟世界大讲堂 希望政安晨的博客能够对您有所裨益&a…

多层感知机 + 代码实现 - 动手学深度学习v2 | 李沐动手学深度学习课程笔记

感知机 感知机≈二分类问题 感知机和其他问题的对比 训练感知机 如果小于等于零&#xff0c;说明预测错啦 &#xff0c;其实就是同号为正&#xff0c;异号为负 举个分类的例子 增加样本&#xff0c;改变分类线 继续分类 感知机的收敛定理 XOR问题 XOR问题其实就是第1、3象限数…

前端学习第七天-css常用样式设置

达标要求 掌握元素的显示与隐藏 熟练应用溢出的文字隐藏 熟练掌握版心和布局流程 1. 元素的显示与隐藏 在CSS中有三个显示和隐藏的单词比较常见&#xff0c;我们要区分开&#xff0c;他们分别是 display visibility 和 overflow。 他们的主要目的是让一个元素在页面中消失…

外包干了6个月,技术退步明显

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

(学习日记)2024.03.01:UCOSIII第三节 + 函数指针 (持续更新文件结构)

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

java-ssm-jsp-宠物护理预定系统

java-ssm-jsp-宠物护理预定系统 获取源码——》公主号&#xff1a;计算机专业毕设大全

勇敢尝鲜之Springboot3大坑-集成Mybatisplus报错:ddlApplicationRunner

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

【LeetCode-1143】最长公共子序列(动归)

目录 题目描述 解法1&#xff1a;动态规划 代码实现 题目链接 题目描述 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长公共子序列的长度。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除…

python识别并控制操作已打开的浏览器进行自动化测试

前提&#xff1a;已安装python和selenium 一、将浏览器以debugger模式打开 打开方法&#xff1a; 1.右击浏览器&#xff0c;选择属性&#xff1a; 2.在目标中加上 --remote-debugging-port9222 --user-data-dir"C:\selenum\AutomationProfile" 二、识别代码 from…

java面试题(spring框架篇)(黑马 )

树形图&#xff1a; 一、Spring框架种的单例bean是线程安全吗&#xff1f; Service Scope("singleton") public class UserServiceImpl implements UserService{ } singleton:bean在每个Spring IOC容器中只有一个实例 protype&#xff1a;一个bean的定义可以有多个…

加密与安全_探索签名算法

文章目录 概述应用常用数字签名算法CodeDSA签名ECDSA签名小结 概述 在非对称加密中&#xff0c;使用私钥加密、公钥解密确实是可行的&#xff0c;而且有着特定的应用场景&#xff0c;即数字签名。 数字签名的主要目的是确保消息的完整性、真实性和不可否认性。通过使用私钥加…

从零开始手写RPC框架(3)——ZooKeeper入门

目录 ZooKeeper简介ZooKeeper中的一些概念 ZooKeeper安装与常用命令常用命令 ZooKeeper Java客户端 Curator入门 ZooKeeper简介 是什么&#xff1f; ZooKeeper 是一个开源的分布式协调服务&#xff0c;本身就是一个分布式程序&#xff08;只要半数以上节点存活&#xff0c;Zo…

Vue+SpringBoot打造海南旅游景点推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…

酷开科技,让酷开系统成为现代生活的变革者

电视&#xff0c;从问世就一直受到人们的追捧。还记得小时候一家人围坐在电视机前的场景&#xff0c;小小的黑白屏幕&#xff0c;牢牢的吸引着大家的目光。随着科技的不断进步&#xff0c;我们的生活也发生了翻天覆地的变化。而电视&#xff0c;也从笨重的黑白电视变成了轻薄的…