目录
[1 默认场景和Assets里的场景](#1 默认场景和Assets里的场景)
[1.1 scene的作用](#1.1 scene的作用)
[1.2 scene作为project的入口](#1.2 scene作为project的入口)
[1.3 默认场景](#1.3 默认场景)
[2 场景scene相关](#2 场景scene相关)
[2.1 创建scene](#2.1 创建scene)
[2.2 切换场景](#2.2 切换场景)
[2.3 build中的场景,在构建中包含的场景](#2.3 build中的场景,在构建中包含的场景)
[2.4 Scenes in Build 的 场景索引](#2.4 Scenes in Build 的 场景索引)
[3 场景相关信息](#3 场景相关信息)
[3.1 场景名称 scene.name](#3.1 场景名称 scene.name)
[3.2 场景索引 scene.buildIndex](#3.2 场景索引 scene.buildIndex)
[3.3 场景路径 scene.path](#3.3 场景路径 scene.path)
[3.4 scene.GetRootGameObjects();](#3.4 scene.GetRootGameObjects();)
[4 场景相关测试](#4 场景相关测试)
[4.1 获取当前场景 SceneManager.GetActiveScene()](#4.1 获取当前场景 SceneManager.GetActiveScene())
[4.2 跳转场景 SceneManager.LoadScene();](#4.2 跳转场景 SceneManager.LoadScene();)
[4.2.1 具体参数](#4.2.1 具体参数)
[4.3 场景是否已经加载 scene.isLoaded](#4.3 场景是否已经加载 scene.isLoaded)
[5 测试代码](#5 测试代码)
[5.1 因为用到场景管理SceneManagement](#5.1 因为用到场景管理SceneManagement)
[需要额外导入UnityEngine 和 UnityEngine.SceneManagement;](#需要额外导入UnityEngine 和 UnityEngine.SceneManagement;)
[5.2 第1次测试代码和结果(有错误)](#5.2 第1次测试代码和结果(有错误))
[5.2.1 其他都OK,但是地图生效了,但是读到的信息还是上一张地图的](#5.2.1 其他都OK,但是地图生效了,但是读到的信息还是上一张地图的)
[5.2.2 原因1](#5.2.2 原因1)
[5.2.3 原因2](#5.2.3 原因2)
[5.3 正确代码](#5.3 正确代码)
1 默认场景和Assets里的场景
1.1 scene的作用
- 游戏里的资源组织
- unity里的资源组织 / 或者说 层级关系
- scene1 → gameobjects → componenets
- scene2 → gameobjects → componenets
1.2 scene作为project的入口
- unity的游戏工程,一般需要通过scene才能进入
- Hierarchy(层级窗口) 里一般看到的是当前场景
- project (工程窗口)里可以看到,project下的Assets里,有一个Scenes文件夹,里面存放着project下的所有场景。
1.3 默认场景
- 游戏里的默认场景是 SampleScene
- 一般新建工程都会默认进入这个场景SampleScene
- 同时,你也可以在 Assets\ Scenes 里找到SampleScene这个场景
2 场景scene相关
2.1 创建scene
- 在project 里创建,选择地图即可。
2.2 切换场景
- 双击场景,即可在场景之间切换
2.3 build中的场景,在构建中包含的场景
(否则会认为是失效的Scene)
- 选择 File / build Settings / Scenes in Build
- 把新建的场景拖入到 Scenes in Build来
2.4 Scenes in Build 的 场景索引
- Scenes in Build 的场景索引
- 后面显示的,0,1,2 就是索引
3 场景相关信息
3.1 场景名称 scene.name
- //场景名称
- scene.name
3.2 场景索引 scene.buildIndex
- //场景索引
- scene.buildIndex
3.3 场景路径 scene.path
- //场景路径
- scene.path
3.4 scene.GetRootGameObjects();
- scene.GetRootGameObjects()
- 获得场景 scene下面的所有gb
- scene.GetRootGameObjects().Length
- 获得场景 scene下面的所有gb的数量,就是长度
4 场景相关测试
4.1 获取当前场景 SceneManager.GetActiveScene()
- //获取当前场景
- SceneManager.GetActiveScene()
- SceneManager.GetActiveScene() 返回值:会返回一个场景
- Scene scene=SceneManager.GetActiveScene();
4.2 跳转场景 SceneManager.LoadScene();
- //跳转场景,可以使用 场景名,或者场景索引
- SceneManager.LoadScene(2);
- SceneManager.LoadScene("Scene2");
4.2.1 具体参数
只加载1个,替换之前的Scene
- SceneManager.LoadScene("Scene2") 默认方式是 LoadSceneMode.Single
- SceneManager.LoadScene("Scene2",LoadSceneMode.Single)
新的场景加载,老的也在,相当于同时都加载生效
- SceneManager.LoadScene("Scene2",LoadSceneMode.Additive)
4.3 场景是否已经加载 scene.isLoaded
- //场景是否已经加载
- Debug.Log(scene.isLoaded);
- 返回 T/ F
5 测试代码
5.1 因为用到场景管理SceneManagement
需要额外导入UnityEngine 和 UnityEngine.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
5.2 第1次测试代码和结果(有错误)
5.2.1 其他都OK,但是地图生效了,但是读到的信息还是上一张地图的
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
///先查看当前Scene
//获取当前场景
Scene scene1=SceneManager.GetActiveScene();
//场景名称
Debug.Log(scene1.name);
//场景路径
Debug.Log(scene1.path);
//场景索引
Debug.Log(scene1.buildIndex);
GameObject[] gb1=scene1.GetRootGameObjects();
Debug.Log(gb1.Length);
//跳转场景
//SceneManager.LoadScene(2);
SceneManager.LoadScene("Scene2");
//获取当前场景
//新定义1个scene2 Scene scene2=
Scene scene2=SceneManager.GetActiveScene();
//场景是否已经加载
Debug.Log(scene2.isLoaded);
///再次查看当前Scene
//场景名称
Debug.Log(scene2.name);
//场景路径
Debug.Log(scene2.path);
//场景索引
Debug.Log(scene2.buildIndex);
GameObject[] gb2=scene2.GetRootGameObjects();
Debug.Log(gb2.Length);
}
// Update is called once per frame
void Update()
{
}
}
5.2.2 原因1
- 场景已经从 Scene1 切换到Scene2 了
- 但是日志里取到的还是 Scene1的内容,这是为什么?
- 因为SceneManager.LoadScene方法默认是异步的,新加载的地图可能还没有加载好,而马上去读取信息读取的就还是上一张地图的信息
- 需要等待新地图加载完成后,就可以了
在Unity中,SceneManager.LoadScene方法默认是异步的,这意味着场景的加载和激活是分开的两个步骤。
当你调用SceneManager.LoadScene("Scene2")时,场景开始加载,但并不会立即激活。
如果代码继续执行,可能会在场景完全加载之前就获取场景信息,这时获取的仍然是上一个场景的信息。
5.2.3 原因2
有可能是场景加载模式问题
- 在 Unity 里,SceneManager.LoadScene 有两种加载模式:LoadSceneMode.Single(默认)和 LoadSceneMode.Additive。
- 若采用 LoadSceneMode.Additive 模式加载场景,新场景会叠加到当前场景之上,上一个场景的对象不会被卸载,这就可能致使获取到上一个场景的信息。
- LoadSceneMode.Additive
- SceneManager.LoadScene(2, LoadSceneMode.Additive); 这样会导致2个场景都加载,读取时会读到上一个场景的信息
- 确保使用默认的 LoadSceneMode.Single 模式加载场景,此模式会卸载当前场景并加载新场景。
- 比如 SceneManager.LoadScene(2);
5.3 正确代码
- 等待新地图加载后,再读取新地图信息就OK了
- 如果读取太早,新Scene还没加载进来,读的还是老的Scene的信息
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
///先查看当前Scene
//获取当前场景
Scene scene1=SceneManager.GetActiveScene();
//场景名称
Debug.Log(scene1.name);
//场景路径
Debug.Log(scene1.path);
//场景索引
Debug.Log(scene1.buildIndex);
GameObject[] gb1=scene1.GetRootGameObjects();
Debug.Log(gb1.Length);
//跳转场景
//SceneManager.LoadScene(2);
//SceneManager.LoadScene("Scene2");
//调用异步的Start1
Start1();
}
async void Start1()
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(2);
// 等待场景加载完成
while (!asyncLoad.isDone)
{
await System.Threading.Tasks.Task.Yield();
}
// 场景加载完成后获取信息
Debug.Log(SceneManager.GetActiveScene().name);
//获取当前场景
//新定义1个scene2 Scene scene2=
Scene scene2=SceneManager.GetActiveScene();
//场景是否已经加载, 但是可能还没有激活新的Scene
Debug.Log(scene2.isLoaded);
///再次查看当前Scene
//场景名称
Debug.Log(scene2.name);
//场景路径
Debug.Log(scene2.path);
//场景索引
Debug.Log(scene2.buildIndex);
GameObject[] gb2=scene2.GetRootGameObjects();
Debug.Log(gb2.Length);
}
// Update is called once per frame
void Update()
{
}
}