1. 程式人生 > 其它 >閱讀國外Coder教程時的筆記,Object Management篇(四)

閱讀國外Coder教程時的筆記,Object Management篇(四)

技術標籤:Unity

原文地址:https://catlikecoding.com/unity/tutorials/object-management/multiple-scenes/
閱讀國外Coder教程時的筆記,Object Management篇(一)
閱讀國外Coder教程時的筆記,Object Management篇(二)
閱讀國外Coder教程時的筆記,Object Management篇(三)
1.上個教程簡單說了可以通過名稱空間UnityEngine.SceneManagerment下的CreateScene和MoveGameObjectToScene實現臨時場景的建立以及將臨時物體比如預製體放入臨時場景。當然,我們也可以通過Create建立新的場景,比如遊戲中經常通過不同場景管理不同的關卡。一個Hierarchy面板下是可以同時存在不同的場景的,當然你需要調整下MainCamera和DirectionLight的數量。這裡注意我們需要到build setting下新增場景到build裡面,否則遊戲打包時場景是不會被匯出的。

在這裡插入圖片描述
這裡後面會有0和1的數字,代表的是Scene的索引。SceneManager.GetSceneByIndex需要傳入的引數就是這裡的數字。

2.SceneManager下的幾個API
SceneManager.LoadScene 載入場景。注意,場景是可以重複載入的。如果不通過條件過濾,會出現同一場景重複出現的問題。
這裡傳入的引數除了Scene的string名字以外,還需要設定SceneMode,有Additive和Single兩種模式,前者是在原有基礎上再開啟一個場景的意思(即同時存在),後者是關閉所有場景只打開載入的場景,需要注意區分。
SceneManager.SetActiveSecene(Scene scene)

顧名思義,設定Active scene。這裡知道的是Light是跟著Active Scene走的。如果你的場景同時存在兩個Scene,但是active scene裡沒有Light,那麼你的場景就是黑的。
SceneManager.GetSceneByName 通過名字查詢場景
SceneManager.GetSceneByIndex 通過索引查詢場景

3.有關燈光烘培
有時候我們會發現Unity的燈光顯示很詭異,這個時候我們需要手動烘培以下燈光。具體操作,開啟需要烘培燈光的場景設定為Active scene(可以在Hierarchy面板裡設定),工具欄Windows/Rendering/Light裡,取消勾選Auto Generate,然後點下Generate Lighting,過一會兒scene資料夾下就會生成lighting的檔案。然後燈光就恢復正常了。

在這裡插入圖片描述
在這裡插入圖片描述
4.載入場景是需要耗時的
如果專案大,場景載入是很耗時的,比如下面這段程式碼執行時可能會報錯。原因是場景還沒加載出來,SceneManager.SetActiveScene只能設定已經加載出來的場景。

		SceneManager.LoadScene("Level 1", LoadSceneMode.Additive);
		SceneManager.SetActiveScene(SceneManager.GetSceneByName("Level 1"));

我們可以通過協程改寫以下,比如:

	IEnumerator LoadLevel () {
		SceneManager.LoadScene("Level 1", LoadSceneMode.Additive);
		yield return null;
		SceneManager.SetActiveScene(SceneManager.GetSceneByName("Level 1"));
	}

一句yield return null 可以為我們爭取一幀的時間。當然我們知道這不是最終解決方法。這裡我們可以用到非同步載入,比如:

	IEnumerator LoadLevel () {
		yield return SceneManager.LoadSceneAsync(
			"Level 1", LoadSceneMode.Additive
		);
		SceneManager.SetActiveScene(SceneManager.GetSceneByName("Level 1"));
	}

大致意思相同,不同的是LoadSceneAsync會幫你check場景是否已經加載出來了,然後才會到下一步。
PS:UnLoadSceneAsync則可以移除場景。
到這裡,還有可以完善的地方。即便你把上面這個協程寫到awake裡面,還是有可能會在載入場景的時候Update運行了幾幀,可以通過以下方法解決。

	IEnumerator LoadLevel () {
		enabled = false;
		yield return SceneManager.LoadSceneAsync(
			"Level 1", LoadSceneMode.Additive
		);
		SceneManager.SetActiveScene(SceneManager.GetSceneByName("Level 1"));
		enabled = true;
	}

大致意思就是,一開始禁用指令碼中所有語句,只有到enabled為true的時候才可以執行。

以上,希望可以幫助到大家學習。