Unity 使用过程中关卡加载和卸载是大多数三维引擎都要提供的基本功能。
因为关卡切换在游戏中非常常用。
在之前的版本中Unity的关卡切换使用的是:
Application.loadedLevel();
看看Application类,此时这个类的功能比较繁杂,比较多。只看与关卡相关的:
[Obsolete("Use SceneManager.LoadScene")]
public static void LoadLevel(string name);
[Obsolete("Use SceneManager.LoadScene")]
public static void LoadLevel(int index);
[Obsolete("Use SceneManager.LoadScene")]
public static void LoadLevelAdditive(string name);
[Obsolete("Use SceneManager.LoadScene")]
public static void LoadLevelAdditive(int index);
//
// 摘要:
// ///
// Unloads all GameObject associated with the given scene. Note that assets are
// currently not unloaded, in order to free up asset memory call Resources.UnloadAllUnusedAssets.
// ///
//
// 参数:
// index:
// Index of the scene in the PlayerSettings to unload.
//
// scenePath:
// Name of the scene to Unload.
//
// 返回结果:
// ///
// Return true if the scene is unloaded.
// ///
[Obsolete("Use SceneManager.UnloadScene")]
public static bool UnloadLevel(string scenePath);
//
// 摘要:
// ///
// Unloads all GameObject associated with the given scene. Note that assets are
// currently not unloaded, in order to free up asset memory call Resources.UnloadAllUnusedAssets.
// ///
//
// 参数:
// index:
// Index of the scene in the PlayerSettings to unload.
//
// scenePath:
// Name of the scene to Unload.
//
// 返回结果:
// ///
// Return true if the scene is unloaded.
// ///
[Obsolete("Use SceneManager.UnloadScene")]
public static bool UnloadLevel(int index);
注解:
这是之前的Application中的关卡的加载和卸载。
当然现在在新版本(Unity5.3以上)中,有了新的变化,那就是SceneManager类了处理。
自从Unity5.3版本,Unity 的关卡切换就添加了新的SceneManager的类来处理。
当然要安装过了Unity文档帮助,并且给下面路径一样,就可以知道在本地打开。
本地链接:
file:///C:/Program%20Files/Unity5.3.0/Editor/Data/Documentation/en/Manual/UpgradeGuide53.html
也可以在Unity中搜索SceneManager来查看。
#region 程序集 UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// H:\Unity\UnityProject\ShiftLevels\Library\UnityAssemblies\UnityEngine.dll
#endregion
using UnityEngine.Internal;
namespace UnityEngine.SceneManagement
{
//
// 摘要:
// ///
// Scene management at run-time.
// ///
public class SceneManager
{
public SceneManager();
public static int sceneCount { get; }
//
public static int sceneCountInBuildSettings { get; }
public static Scene GetActiveScene();
public static Scene[] GetAllScenes();
// 参数:
// index:
// Index of the scene to get. Index must be greater than or equal to 0 and less
// than SceneManager.sceneCount.
public static Scene GetSceneAt(int index);
// 返回结果:
// ///
// The scene if found or an invalid scene if not.
// ///
public static Scene GetSceneByName(string name);
// Searches all scenes added to the SceneManager for a scene that has the given
// asset path.
// ///
//
// 参数:
// scenePath:
// Path of the scene. Should be relative to the project folder. Like: "AssetsMyScenesMyScene.unity".
public static Scene GetSceneByPath(string scenePath);
[ExcludeFromDocs]
public static void LoadScene(int sceneBuildIndex);
[ExcludeFromDocs]
public static void LoadScene(string sceneName);
// 参数:
// sceneName:
// Name of the scene to load.
//
// sceneBuildIndex:
// Index of the scene in the Build Settings to load.
//
// mode:
// Allows you to specify whether or not to load the scene additively. See SceneManagement.LoadSceneMode
// for more information about the options.
public static void LoadScene(int sceneBuildIndex, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
// 参数:
// sceneName:
// Name of the scene to load.
//
// sceneBuildIndex:
// Index of the scene in the Build Settings to load.
//
// mode:
// Allows you to specify whether or not to load the scene additively. See SceneManagement.LoadSceneMode
// for more information about the options.
public static void LoadScene(string sceneName, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
[ExcludeFromDocs]
public static AsyncOperation LoadSceneAsync(int sceneBuildIndex);
[ExcludeFromDocs]
public static AsyncOperation LoadSceneAsync(string sceneName);
// 参数:
// sceneName:
// Name of the scene to load.
//
// sceneBuildIndex:
// Index of the scene in the Build Settings to load.
//
// mode:
// If LoadSceneMode.Single then all current scenes will be unloaded before loading.
public static AsyncOperation LoadSceneAsync(int sceneBuildIndex, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
// 参数:
// sceneName:
// Name of the scene to load.
//
// sceneBuildIndex:
// Index of the scene in the Build Settings to load.
//
// mode:
// If LoadSceneMode.Single then all current scenes will be unloaded before loading.
public static AsyncOperation LoadSceneAsync(string sceneName, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
//
// 参数:
// sourceScene:
// The scene that will be merged into the destination scene.
//
// destinationScene:
// Existing scene to merge the source scene into.
public static void MergeScenes(Scene sourceScene, Scene destinationScene);
//
// 摘要:
// ///
// Move a GameObject from its current scene to a new scene. /// It is required that
// the GameObject is at the root of its current scene.
// ///
//
// 参数:
// go:
// GameObject to move.
//
// scene:
// Scene to move into.
public static void MoveGameObjectToScene(GameObject go, Scene scene);
//
// 返回结果:
// ///
// Returns false if the scene is not loaded yet.
// ///
public static bool SetActiveScene(Scene scene);
// ///
public static bool UnloadScene(string sceneName);
//
// 摘要:
// ///
// Unloads all GameObjects associated with the given scene. Note that assets are
// currently not unloaded, in order to free up asset memory call Resources.UnloadAllUnusedAssets.
// ///
//
// 参数:
// sceneBuildIndex:
// Index of the scene in the Build Settings to unload.
//
// sceneName:
// Name of the scene to unload.
//
// 返回结果:
// ///
// Returns true if the scene is unloaded.
// ///
public static bool UnloadScene(int sceneBuildIndex);
}
}
(一)
SceneManager
class in UnityEngine.SceneManagement
描述:运行时的场景管理。
静态变量sceneCount: 当前加载的场景的总数。
前加载的场景的数量将被返回。
sceneCountInBuildSettings : 在BuildSettings的号码。
(二)
CreateScene:在运行时创建一个空的新场景,使用给定的名称。
在运行时创建一个空的新场景,使用给定的名称。
新的场景将开放相加到层次与现有已经打开的场景。新场景的路径将是空的。此函数用于在运行时创建场景。创建一个场景编辑时间(例如,使编辑脚本或工具需要创建场景时),使用editorscenemanager.newscene。
(三)
public static SceneManagement.Scene GetActiveScene()
现场的活动场景。
描述:获取当前活动场景。
当前活动的场景将被用来作为目标由脚本实例化新的游戏对象现场。
using UnityEngine;
using UnityEngine.SceneManagement;
public class GetActiveSceneExample : MonoBehaviour
{
void Start()
{
Scene scene = SceneManager.GetActiveScene();
Debug.Log("Active scene is '" + scene.name + "'.");
}
}
(四)
public static SceneManagement.Scene GetSceneAt(int index);
index:场景索引。指数必须大于或等于0和小于scenemanager.scenecount。
返回:
根据给定的参数返回一个场景引用。
获取现场在添加场景的场景管理器的列表索引:
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
using UnityEngine;
public class Example
{
// adds a menu item which gives a brief summary of currently open scenes
[MenuItem("SceneExample/Scene Summary")]
public static void ListSceneNames()
{
string output = "";
if (SceneManager.sceneCount > 0)
{
for (int n = 0; n < SceneManager.sceneCount; ++n)
{
Scene scene = SceneManager.GetSceneAt(n);
output += scene.name;
output += scene.isLoaded ? " (Loaded, " : " (Not Loaded, ";
output += scene.isDirty ? "Dirty, " : "Clean, ";
output += scene.buildIndex >=0 ? " in build)\n" : " NOT in build)\n";
}
}
else
{
output = "No open scenes.";
}
EditorUtility.DisplayDialog("Scene Summary",output, "Ok");
}
}
(五)
public static SceneManagement.Scene GetActiveScene();
获取当前活动场景。
当前活动的场景将被用来作为目标由脚本实例化新对象。
using UnityEngine;
using UnityEngine.SceneManagement;
public class GetActiveSceneExample : MonoBehaviour
{
void Start()
{
Scene scene = SceneManager.GetActiveScene();
Debug.Log("Active scene is '" + scene.name + "'.");
}
}
public static void LoadScene(int sceneBuildIndex, SceneManagement.LoadSceneMode mode = LoadSceneMode.Single);
public static void LoadScene(string sceneName, SceneManagement.LoadSceneMode mode = LoadSceneMode.Single);
sceneName: 需发加载的场景名称或路径。
sceneBuildIndex:在“ Build Settings”加载中的场景的索引。
Mode:允许您指定是否要加载相加现场。见LoadScene模式有关选项的详细信息。
LoadSceneMode:在播放器加载一个场景时使用。
Single:关闭所有当前场景和加载一个新场景。
Additive:将场景添加到当前加载的场景中。
你可以使用这个异步版本:LoadSceneAsync。
using UnityEngine;
using UnityEngine.SceneManagement;
public class ExampleClass : MonoBehaviour {
void Start () {
// Only specifying the sceneName or sceneBuildIndex will load the scene with the Single mode
SceneManager.LoadScene ("OtherSceneName", LoadSceneMode.Additive);
}
}
上代码:
/**************************************************************************
Copyright:@maxdong
Author: maxdong
Date: 2017-07-04
Description:加载关卡,可以分组加载和卸载。使用Unity版本为5.3.0.
因为里面使用了场景管理的一个类,这个类在5.3.0以上版本才添加的。
测试操作:使用空格键来切换场景,然后间隔5秒后才开始卸载。
**************************************************************************/
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
[System.Serializable]
public class LevelOrder
{
[Header("每组关卡名称")]
public string[] LevelNames;
}
public class ChangLevelsHasMain : MonoBehaviour
{
[Header("所有关卡列表")]
public LevelOrder[] levelOrder;
private static int index;
private int totalLevels = 0;
private int levelOrderLength;
void Start ()
{
for (int i = 0; i < levelOrder.Length; i++)
{
totalLevels += levelOrder[i].LevelNames.Length;
}
if (totalLevels != SceneManager.sceneCountInBuildSettings)
{
}
levelOrderLength = levelOrder.Length;
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown(KeyCode.Space))
{
bool isOk = LoadNextLevels();
if (isOk)
{
InvokeRepeating("UnloadLastLevel", 2.0f, 5);
}
}
}
bool LoadNextLevels()
{
bool bResult = true;
//index = index % levelOrderLength;
if (index < 0 || index >= levelOrderLength)
{
bResult = false;
return bResult;
}
int LoadTimes = levelOrder[index].LevelNames.Length;
for (int i = 0; i < LoadTimes; i++)
{
SceneManager.LoadSceneAsync(levelOrder[index].LevelNames[i], LoadSceneMode.Additive);
}
return bResult;
}
void UnloadLastLevel()
{
if (index == 0)
{
index++;
CancelInvoke("UnloadLastLevel");
return;
}
// 上一組的關卡
int TmpLast = (index - 1) >= 0 ? (index - 1) : levelOrderLength - 1;
int LoadTimes = levelOrder[index].LevelNames.Length;
for (int i = 0; i < LoadTimes; i++)
{
Scene Tmp = SceneManager.GetSceneByName(levelOrder[index].LevelNames[i]);
if (!Tmp.isLoaded)
{
return;
}
}
// 下一關卡全部加載完畢後,卸載之前關卡
for (int i = 0; i < levelOrder[TmpLast].LevelNames.Length; i++)
{
SceneManager.UnloadScene(levelOrder[TmpLast].LevelNames[i]);
}
index++;
CancelInvoke("UnloadLastLevel");
}
}
就这样就可以了。
代码主要是按组来加载关卡,然后按组来卸载。
测试中,按下空格键来加载,每组关卡在一定时间后,(这里设置的5秒)自动卸载前一组关卡。这里主地图是不卸载的,会一直存在的。