异步加载场景与异步加载游戏资源
Application.LoadLevel 加载关卡
在同步加载游戏场景的时候通常会使用方法Application.LoadLevel 加载关卡。
该方法在执行完Application.LoadLevel方法后,会把该场景在 Hierarchy 视图中的所有游戏对象加载至内存当中。因为Application.LoadLevel,若是场景内游戏对象过多,则会在加载的瞬间卡顿一下。
因为 LoadLevel()方法是同步进行的。
Object.Instantiate 实例化
C# => static Object Instantiate(Object original, Vector3 position, Quaternion rotation);
C# => static Object Instantiate(Object original);
克隆原始物体,位置设置在position,设置旋转在rotation,返回的是克隆后的物体。这实际上在Unity和使用复制(ctrl+D)命令是一样的,并移动到指定的位置。如果一个游戏物体,组件或脚本实例被传入,实例将克隆整个游戏物体层次,以及所有子对象也会被克隆。所有游戏物体被激活。
Instantiate通过脚本动态的创建出来的游戏对象的,属于后天加载。
异步加载游戏场景
异步加载的方式分为两种:
第一种:加载新游戏场景,当新场景加载完成后进入新场景并且销毁旧场景。
Application.LoadLevelAsync 异步加载关卡
第二种:新场景加载完毕后,保留旧场景的游戏对象并且进入新场景。
Application.LoadLevelAdditiveAsync 异步累加关卡
异步加载的游戏 LOADING 界面
例如从场景1进入场景2,可以建立一个过渡的LOADING场景,先从场景1读取LOADING场景,当异步加载完成后再从LOADING场景进入场景2。因为LOADING场景仅仅只是绘制进度条或过渡动画,所以该场景的加载应该是瞬间就可以完成的。
这个方法需要使用MonoBehaviour.StartCoroutine 开始协同程序
MonoBehaviour.StartCoroutine 开始协同程序
注意:
AsyncOperation.progress 进度
C# => float progress;
Description 描述
What’s the operation’s progress (Read Only)
操作的进度是多少?(只读)
progress 的取值范围在 0.1-1 之间,但是它不会等于 1,也就是说 progress 可能是 0.8 或者 0.9 的时候就直接进入新场景了
AsyncOperation.isDone 是否完成
JavaScript => var isDone: bool;
C# => bool isDone;
Description 描述
Has the operation finished? (Read Only)
有操作完成了吗?(只读)
在游戏场景中加载对象
在 Hierarchy 视图中设置游戏对象的active为false,可以让游戏对象不会在切换场景时被加载。
当需要加载大型场景时,可以先把场景内的游戏对象的active全部设置为false,然后在场景加载完成时开启一个协同程序一个一个加载显示出来。
编辑器赋值与代码中赋值的区别
编辑器中赋值所消耗的时间都会记在 loadlevel()读取场景中。
代码中使用Resource.load()这类方法所消耗的时间会记在脚本中。
而使用 Instantiate();方法来动态的创建游戏对象没有什么时间上的消耗的,一般都会在1毫秒内就能完成。有一些特殊的模型会消耗一定的时间,但很少见,比如某些UGUI的UI模型比较复杂,在生成的时候会花费一定的时间。
问题:Thread 可以代替StartCoroutine()吗
答案是不行,比如查询数据库的时候如果用 Thread 的话 Unity 就会报错说不能在线程中查询,但是在 StartCoroutine()
中就可以完成,所以开发中大家可以尝试着使用它,我们还可以使用 StopCoroutine(“name”)来关闭一个正在执行的异步线程。
本文固定链接: https://www.xuanyusong.com/archives/1427
转载请注明: 雨松MOMO 2012年07月01日 于 雨松MOMO程序研究院 发表
Unity 关于资源加载的时间消耗
(转自:http://www.taidous.com/forum.php?mod=viewthread&tid=42773&extra=page%3D1&page=1)
一般来说把一个预设物体生成在场景里面需要这么几个步骤:
- 加载文件,如果是内部Resource文件就不需要加载文件,但AssetBundle是需要先加载某个文件,再转成AssetBundle的。
- 读取资源,可能是Resource.Load,或者是AssetBundle.LoadAsset,把资源读成Object
- 生成模型,一般是使用GameObject.Instantiate方法把Object生成为GameObject
测试结果出来了,可以分析一下问题的所在:
不难看出,基本的时间消耗都在读取资源那一步。而且读取单一的文件,会比同一个文件拆分多个依赖读取需要的时间短。这里我们可以得出一些结论:
- 读取完的资源尽量保存起来,下次再请求读取的时候就可以直接返回结果。
- 再次说明了资源的依赖不要拆得太散,能不拆尽量不拆,不然虽然在容量上占优势了,但加载的时候卡,也是得不偿失的。
- 由于读取大文件的时间还是长,以30fps算,一帧也才33毫秒的时间,并不能处理很多读取资源的业务。所以可以考虑异步读取资源或者提前读取资源,然后保存起来备用。