Unity 场景API详解
本文提供全图文流程,中文翻译。
Chinar 坚持将简单的生活方式,带给世人!
(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)
Chinar —— 心分享、心创新!
助力快速理解 Unity 场景管理的 API 诸多用法
给新手节省宝贵的时间,避免采坑!
Chinar 教程效果:
全文高清图片,点击即可放大观看 (很多人竟然不知道)1
SceneManager —— 场景管理
我们在游戏开发中,经常用到关卡切换、场景切换、加载场景等诸多功能性操作
Unity 为我们提供了场景管理类,可以很方便的对场景进行各类操作
下边我们就来逐一的看一下,API中的函数具体用法
另附——
官方API链接 其他2
API —— API(创建/获取/加载)
直接给大家贴上中文注释,便于初学者学习
其他易出错的函数, Chinar 也用了简单例子做了说明,避免初学者踩坑!
提示:
其中 0 号场景为: SampleScene
其中 1 号场景为: Chinar
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 场景管理测试类
/// </summary>
public class ChinarSceneManager1 : MonoBehaviour
{
/// <summary>
/// 初始化函数
/// </summary>
void Start()
{
SceneManager.CreateScene("Chinar"); //使用给定名称在运行时创建一个空的新场景
SceneManager.GetActiveScene(); //获取当前活动的场景
SceneManager.GetSceneAt(0); //在SceneManager的已加载场景列表中获取索引处的场景
SceneManager.GetSceneByBuildIndex(0); //从构建Build Setting中索引获取Scene结构
SceneManager.GetSceneByName("Chinar"); //搜索给定名称的场景
SceneManager.GetSceneByPath("Assets/Scenes/SampleScene.unity"); //搜索给定路径的场景
SceneManager.LoadScene(1); //根据“Build Setting”中索引加载场景
SceneManager.LoadScene("Chinar"); //根据“Build Setting”中名称加载场景
SceneManager.LoadScene(1, LoadSceneMode.Additive); //加载场景,加载方式:保留当前场景,附加指定场景
SceneManager.LoadScene("Chinar", LoadSceneMode.Single); //加载场景,加载方式:关闭所有当前加载的场景并加载场景
SceneManager.LoadSceneAsync(1); //根据下标,在后台异步加载场景
SceneManager.LoadSceneAsync("Chinar"); //根据名称,在后台异步加载场景
SceneManager.LoadSceneAsync(1, LoadSceneMode.Additive); //异步加载,方式:附加
SceneManager.LoadSceneAsync(1); //异步加载,方式:单一
SceneManager.UnloadSceneAsync("Chinar"); //销毁与给定场景关联的所有GameObject,并从SceneManager中移除场景。
}
}
3
API (Merge) —— 常用API(合并/移动对象/设置活动)
有时我们需要将场景合并
或者将当前场景的游戏对象,移动到其他场景中 / 设置活跃场景
进行这三类操作,都需要先将目标场景加载后,才可保证函数正确执行
这里为了便于初学者理解,我用了协成加载的方式,来做说明
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 场景管理测试类
/// </summary>
public class ChinarSceneManager1 : MonoBehaviour
{
/// <summary>
/// 初始化函数
/// </summary>
void Start()
{
StartCoroutine(MergeMethodEnumerator()); //合并场景
StartCoroutine(MoveGameObjectToSceneEnumerator()); //移动游戏对象到目标场景
StartCoroutine(SetActiveSceneEnumerator()); //设置场景为活动场景
}
/// <summary>
/// 合并场景
/// 必须要保证:要合并的场景被加载后,才可以正确合并
/// 如果物体名称相同,并不会合并,相互独立
/// </summary>
IEnumerator MergeMethodEnumerator()
{
yield return SceneManager.LoadSceneAsync(1, LoadSceneMode.Additive); //等待场景加载完毕后,再向下执行
SceneManager.MergeScenes(SceneManager.GetSceneByBuildIndex(1), SceneManager.GetActiveScene()); //源场景 1,目标场景:当前 —— 将源场景合并到目标场景中
}
/// <summary>
/// 移动游戏对象到新场景
/// 必须要保证:目标场景被加载后,游戏对象才能被正确移动到目标场景中
/// 如果物体名称相同,并不会合并,相互独立
/// </summary>
IEnumerator MoveGameObjectToSceneEnumerator()
{
yield return SceneManager.LoadSceneAsync(1, LoadSceneMode.Additive); //等待场景加载完毕后,再向下执行
SceneManager.MoveGameObjectToScene(GameObject.Find("Cube"), SceneManager.GetSceneByName("Chinar")); //将当前场景中的 Cube,移动到目标场景中
SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene()); //卸载掉当前场景
//如果要加载单个场景,请确保在要移动到新场景的GameObject上使用DontDestroyOnLoad,否则Unity会在加载新场景时删除它。
}
/// <summary>
/// 设置场景为活动场景
/// 必须要保证:目标场景被加载后,才可以正确设置活动状态
/// </summary>
IEnumerator SetActiveSceneEnumerator()
{
yield return SceneManager.LoadSceneAsync(1, LoadSceneMode.Additive); //等待场景加载完毕后,再向下执行
SceneManager.SetActiveScene(SceneManager.GetSceneAt(1)); //设置场景为活动场景
//print(SceneManager.GetSceneAt(1).IsValid());
}
}
4
Scene (Events) —— 场景事件
有时我们需要场景记载/卸载/变更时,进行一系列操作
这时我们需要用事件来完成通知
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 场景管理测试类
/// </summary>
public class ChinarSceneManager1 : MonoBehaviour
{
/// <summary>
/// 初始化函数
/// </summary>
void Start()
{
SceneManager.activeSceneChanged += SceneManager_activeSceneChanged; //订阅此事件可在活动场景发生更改时收到通知。
StartCoroutine(SetActiveSceneEnumerator()); //活动场景切换时,会收到通知,打印输出"活动场景变更了"
SceneManager.sceneLoaded += SceneManager_sceneLoaded; //委托 —— 加载场景时收到通知
SceneManager.LoadSceneAsync(1); //异步加载,加载方式:单一
SceneManager.sceneUnloaded += SceneManager_sceneUnloaded; //委托 —— 卸载Scene时收到通知
}
/// <summary>
/// 设置场景为活动场景
/// 必须要保证:目标场景被加载后,才可以正确设置活动状态
/// </summary>
IEnumerator SetActiveSceneEnumerator()
{
yield return SceneManager.LoadSceneAsync(1, LoadSceneMode.Additive); //等待场景加载完毕后,再向下执行
SceneManager.SetActiveScene(SceneManager.GetSceneAt(1)); //设置场景为活动场景
}
/// <summary>
/// 活动场景变动时被调用
/// </summary>
private void SceneManager_activeSceneChanged(Scene arg0, Scene arg1)
{
print("活动场景变更了");
}
/// <summary>
/// 场景被加载后,被调用
/// </summary>
private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
{
print("场景被加载了");
}
/// <summary>
/// 场景被卸载时,被调用
/// </summary>
private void SceneManager_sceneUnloaded(Scene arg0)
{
print("场景被卸载了");
}
}
5
Scene —— 场景自身的一些属性
Scene 类自身具备一些属性和字段,便于我们对场景的状态进行了解/操作
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 场景管理测试类
/// </summary>
public class ChinarSceneManager1 : MonoBehaviour
{
/// <summary>
/// 初始化函数
/// </summary>
void Start()
{
print(SceneManager.GetActiveScene().buildIndex); //返回“Build Setting”中场景的索引。如果场景是通过AssetBundle加载的,则始终返回-1。
print(SceneManager.GetActiveScene().isDirty); //如果场景被修改,则返回true。
print(SceneManager.GetActiveScene().isLoaded); //如果加载场景,则返回true。
print(SceneManager.GetActiveScene().name); //返回场景的名称。
print(SceneManager.GetActiveScene().path); //返回场景的相对路径。喜欢:“Assets/Scenes/SampleScene.unity”。
print(SceneManager.GetActiveScene().rootCount); //返回场景的游戏对象个数
print(SceneManager.GetActiveScene().GetHashCode()); //返回场景的哈希值
print(SceneManager.GetActiveScene().GetRootGameObjects()); //返回场景中所有游戏对象,是一个GameObject[] 数组
foreach (var a in SceneManager.GetActiveScene().GetRootGameObjects())
{
print(a.name);
}
StartCoroutine(SetActiveSceneEnumerator()); //设置场景为活动场景
print(SceneManager.GetSceneAt(1).IsValid()); //判断场景是否有效,如果场景未被加载/或是不存在,则场景可能无效
}
/// <summary>
/// 设置场景为活动场景
/// 必须要保证:目标场景被加载后,才可以正确设置活动状态
/// </summary>
IEnumerator SetActiveSceneEnumerator()
{
yield return SceneManager.LoadSceneAsync(1, LoadSceneMode.Additive); //等待场景加载完毕后,再向下执行
SceneManager.SetActiveScene(SceneManager.GetSceneAt(1)); //设置场景为活动场景
}
}
May Be —— 搞开发,总有一天要做的事!
拥有自己的服务器,无需再找攻略! Chinar 提供一站式教程,闭眼式创建! 为新手节省宝贵时间,避免采坑! |
END
本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究
对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: [email protected]
对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址