Unity --- 场景/场景管理类 与 异步场景加载法
Posted Metallic Cat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity --- 场景/场景管理类 与 异步场景加载法相关的知识,希望对你有一定的参考价值。
1.一个游戏是由很多的场景组成的,比如游戏的开始页面,战斗场景,商店页面...等等,这些都是一个个游戏场景
或者比如说:一进入游戏,你一开始来到的是新手村这个场景,出了新手村后来到的就是荒野场景,过来荒野场景后来到的就是大城市场景.....
一个游戏是由很多的场景组成的,而每个场景又由很多的游戏物体组成,而每个游戏物体又由很多的脚本组件组成
之前我们一直是在默认的场景中添加游戏物体,其实我们也可以添加新的游戏场景,并通过游戏代码加载新的场景
这个就是一开始Unity自动为我们创建的示例场景(默认场景)
1.新场景的创建:
首先我们要做的是在Assets文件夹下的scene文件夹中创建一个scene(场景)文件,创建好后再将这个场景文件拖拽到Hirarchy层级中,这样一个新的场景就创建好啦
2.我们的期望是:能够通过代码使得游戏程序自动从场景A加载到场景B中
3.实现方法:假定A是示例场景,B是我们创建的新场景
首先点开File中的Build Setting(生成设置)
这个是指构建中的场景
如果我们当前创建的场景不是废弃场景是有用的,我们就要把这个场景从HIrarchy中选中并拖到这个Scenes in Build(构建中的场景)中
拖进去后就会自动给里面的场景进行编号
脱进去之后我们就可以进行场景跳转啦!!!
首先我们可以在任意一个脚本中写场景跳转代码,所以我们随便在一个游戏物体的脚本中进行编写
注意只有被我们加入到了scene in bulid 中的场景才能够在脚本中被调用和访问
首先和场景有关的是下面这两个类
在使用这两个类的时候我们需要引入一个命名空间
引入后如果我们想在一开始就跳转到某个场景(注意这个场景必须已经被放在了构建中的场景的那个框框中了),我们可以在start方法中通过SceneManager类调用静态方法 LoadScene,括号中传的参数可以是我们要加载的场景的场景名,也可以是要加载的场景的场景编号
输入名称的时候要用字符串!
我们如何获取当前激活的场景呢?
1.用Scene场景类创建一个场景对象,然后通过场景管理类调用静态方法获得当前场景并赋值给我们创建的场景对象
向上面这样调用可以获取这个场景对象指向的场景的场景名
如果被加载,这个属性的值是ture,否则为false
上面这个路径指的是对应场景的场景文件的文件路径
获取当前场景在build in scene中的索引
这个方法返回的是一个数组,这个数组的类型是Object,然后这个方法的作用是获取调用它的场景对象所指向的场景中的所有游戏物体
对于场景管理类而言
这个sceneCount是当前加载的场景的数量 --- 场景并不是同一时间只能存在一个,它是能多个叠加起来的
括号内的参数是我们给新场景的命名 (ps:创建了一个新场景后当然也需要我们创建一个场景对象来接收这个新场景啦)
参数是我们要卸载的场景的场景名 --- 卸载后这个场景和对应的场景文件都会被删除
加载场景再拓展:
这个函数还有第二个参数,第二个参数是枚举变量,对应的枚举类型是LoadSceneMode,这个枚举类型中只有两个值
(ps:枚举变量只能被枚举类型中的成员赋值,访问枚举类型中的成员的方法是 枚举类型名 + 点操作符 + 要访问的枚举成员名)
1.当我们给第二个参数赋值LoadSceneMode.Single的时候,这个加载场景方法就会使得当前游戏中有且只有我们给定的场景(第一个参数 -- 要加载的场景名)会被加载
2.当我们给第二个参数赋值LoadSceneMode.Additive(添加剂)的时候,会让我们给定的场景加载,并让这个场景与当前已经加载好的场景同时显示
这个LoadScene场景加载方法其实有一个问题,就是当加载的场景很大很复杂的时候,加载速度会变慢,而且加载时会出现卡顿
为了解决这个问题,人们提供一种新的方法 --- LoadSceneAsync() --- 异步场景加载法
(Async -- 异步)
通过SceneManager调用的LoadSceneAsync() --- 异步场景加载法
以及如何设置加载进度条
1.异步与同步的区别:正常执行代码就像下面一样,从上到下一根筋执行完
假设是上面这样一行行代码执行,前三行代码计算机都能很快的执行完毕,但是到了到了后三行代码时计算机执行代码的速度将显著下降,我们称这种为代码阻滞现象
造成这一现象的原因是后三行代码需要的计算时间和操作时间与其它代码相比明显长了很多
代码阻滞现象会导致整个程序在这几行代码处直接卡住,后面的一些能够快速执行的代码也无法执行了,整个游戏就会出现卡顿
为了解决这个问题人们开发出了异步编程(多线程编程)
当有耗时操作的时候我们就多开一个线程,把耗时操作交给这个线程执行,然后主线程继续执行耗时操作后面的代码,这样就能在执行耗时操作的时候异步执行其它的代码了。
执行耗时操作的线程在执行完毕后将获得的数据直接传回给主线程就OK了
在C#中上面这个异步操作就是通过多线程实现的,而在Unity中则是通过协程实现的
那么我们如何在Unity中创建协程呢?
1.一个协程最好只能够处理一个方法,所以我们首先创建一个在协程中执行的方法:
注意这个方法的返回值一定是 IEnumerator , 在这个方法中写我们想要实现的功能,到时候在写协程中就会调用这个方法并执行方法中的代码
以异步场景加载为例:注意这个LoadSceneAsync()方法只能在协程中通过SceneManager调用,然后这个方法有返回值,返回值的类型是 AsyncOperation,我们要创建一个对应的对象来接收这个返回值
接收到这个返回值后,在协程方法中用 yield(屈服) return 返回
2.协程方法写完之后我们要在MonoBehaviour的方法中开启这个协程:用下面这行代码开启协程,括号里的参数是我们要在协程中执行的协程方法
协程执行完毕后会自动关闭,不需要我们手动关闭
3.如果已经实现了协程异步加载场景了,我们该如何时时刻刻都获取到这个协程中的场景加载进度呢?
在Updata方法中写这行代码就行:
1.异步场景加载的进度可以通过承接异步场景加载方法返回值的场景对象调用progress属性获得
2.Updata方法每一帧都会被调用,所在Updata中输出加载进度我们就可以每一帧都获取到当前场景的加载进度了
3.场景的加载进度,即progress属性的取值范围是0到0.9,当到达0.9的时候场景加载完毕
4.上面这种方法在加载完场景后就会自动跳转到加载好的场景,那有没有办法让我们手动去选择是否跳转呢?
答案是有的:
通过承接把异步场景加载法加载好后的场景的场景对象调用allowSceneActivation属性,这个属性的默认值是true,即允许自动跳转,我们可以把这个默认值手动改为false,这样就不会自动跳转了,然后我们可以设置按钮让玩家控制这个属性的true/false
Unity 场景管理/切换
SceneManager
场景管理器,包含多个与场景管理相关的函数,将这些函数结合使用就能实现多种场景的切换方式,并提高游戏性能。
LoadScene + GetSceneByBuildIndex + LoadSceneMode
在大多数情况下,为了避免在加载时出现暂停或者性能问题,应该使用该函数的异步版本:LoadSceneAsync()。
使用 LoadScene() 时,加载不会立即发生,它会在下一帧中完成。这种半异步行为就可能导致帧断续,并且可能会造成混乱。
它的作用顾名思义就是获取 Build Settings 中场景的下标。
场景为先加载,后激活的,LoadSceneMode(加载模式)有两种:
使用 Slingle 模式:关闭已经加载的所有场景,只加载一个新的场景,新场景将被添加到 SceneManager 的目录当中。
使用 Additive 模式:其他已加载的场景仍然保持激活的状态,同时加载一个新的场景。
SetActiveScene + GetActiveScene
激活已加载的场景,如果场景未加载,则返回 false。
获取已激活的场景。
CreateScene + MergeScenes
运行时创建一个新的场景。
将源场景的内容合并到目标场景当中,并删除源场景;源场景根目录下的所有游戏对象都将移动到目标场景的根目录下。
需要注意的是,该函数具有破坏性 —— 合并完成后,源场景将被销毁。
MoveGameObjectToScene
将 GameObject 从当前场景移动到指定的新场景。
只能将根游戏对象从一个场景移动到另一个场景。这意味着要移动的 GameObject 不能是其他场景中任何其他 GameObject 的子对象。
这仅适用于将 GameObjects 移动到已加载的场景(LoadSceneMode.Additive)。如果要加载单个场景,要确保在移动到新场景的 GameObject 上使用 DontDestroyOnLoad,否则 Unity 就会在加载新场景的时候将它删除。
UnloadSceneAsync
销毁与指定场景关联的所有 GameObject,并从 SceneManager 中移除场景。
指定的场景名称可以是完整的场景路径,也可以是场景名称。如果仅给出场景名称,则将卸载匹配列表中的第一个场景,所以如果有多个具有相同名称但路径不同的场景,就要使用完整的场景路径。
需要注意的是:
-
-
不区分大小写,并且由于它是异步处理,因此无法保证完成的时间。
-
资产目前尚未卸载。为了释放资产内存,可以调用 Resources.UnloadUnusedAssets()。
-
如果没有要加载的场景,则无法使用 UnloadSceneAsync()。例如,只有单个场景的项目就无法使用该函数。
-
***| 以上内容仅为学习参考、学习笔记使用 |***
以上是关于Unity --- 场景/场景管理类 与 异步场景加载法的主要内容,如果未能解决你的问题,请参考以下文章