1. 程式人生 > >Unity場景問題,以及老程式DontDestory問題

Unity場景問題,以及老程式DontDestory問題

Unity 5.3中新增加了多場景編輯功能,允許使用者將一個大場景以某種邏輯分割成多個小場景並方便的編輯和管理。這在某些情況下會比較有用,是對Unity編輯器對場景編輯能力的一個重要提升。

什麼是多場景編輯

多場景編輯就是允許使用者在Unity編輯器中同時開啟多個場景,並對它們進行編輯。Unity提供了一系列的UI和Scripting API來管理這些場景。以下就是一個在Unity編輯器中進行多場景編輯的一個例項:


什麼是場景在進一步瞭解多場景編輯之前,我們先了解下什麼是場景(Scene)。簡而言之場景就是包含了遊戲物件的一個檔案,比如Game Objects,Components等。不過有一些物件可能一些使用者並不會太在意,那就是Scene Game Managers。

Unity中有兩類Game Managers:
  • 一類是Global Game Managers。它們是全域性的Game Managers,包括AudioManager、InputManager、PhysicsManager等。當在Unity5.3中釋出遊戲的時候,你會發現在輸出目錄或者釋出包裡面會有個globalgamemanagers檔案,它包含了所有全域性Game Managers。

  • 另一類是Scene Game Managers。如果你將Editor Settings中的Asset Serialization選擇為“Force Text”模式,並開啟一個已經儲存的*.unity場景檔案,你會發現前儲存在檔案最前面的就是SceneSettings、RenderSettings、LightMapSettings和NavMeshSettings

    ,它們就是每個場景都會有的Game Managers。


為什麼需要多場景編輯
  • 首先,將大場景分割成多個場景,可以更好的支援場景的流式載入(Scene streaming);

  • 其次,可以更好地支援協同合作,尤其是在有原始碼版本管理的時候可以允許多人同時編輯而不會產生衝突;

  • 再者,支援解除安裝場景(Scene Unloading),在5.3之前使用者可以通過Application.LoadLevelAddtive()和Application.LoadLevelAdditiveAsync()動態載入場景,但沒有對應的Application.UnloadScene()。而5.3中提供了場景解除安裝,讓使用者可以更靈活的管理多個場景


多場景編輯基本功能介紹接下來我們看看Unity在5.3中具體提供了哪些多場景編輯的功能。
Scene結構在5.3之前,Unity中只有概念上的場景,而到5.3中我們引入了真正的Scene結構。它包含了name、path、isLoaded等變數,同時也提供了IsValid()以及GetRootGameObjects()方法。
Active Scene在5.3中,我們引入了Active Scene(當前場景)的概念。引入它的目的在於:
  • 如果有多個場景同時開啟,我們會選擇Active Scene的Scene Game Managers作為當前的Scene Game Managers。比如在Bake Lightmapping的時候,我們會使用Active Scene的LightMapSettings來Bake當前開啟的所有場景。

  • 在建立Game Object的時候,會預設加入到Active Scene。


SceneManagerSceneManager在UnityEngine.SceneManagement之下,它是Runtime中的Scene Manager,提供了以下方法:LoadScene() /LoadSceneAsync()
它們允許使用者通過Name、Build Index來載入場景。使用者可以在Build Settings視窗檢視Name和Build Index。通過這兩個方法載入的場景,要麼被加到了Build Settings,要麼存在於AssetBundle之中。如果是從AssetBundle中載入場景,則只能通過名字載入
要說明的是,如果有多個場景同名但位於不同的目錄之下,可以使用完整的路徑(不帶.unity字尾名)來載入不同的場景。
使用者可以通過LoadSceneMode來指定不同的載入模式。LoadSceneMode.Single在載入之前會解除安裝其它所有的場景,LoadSceneMode.Additive則是載入的時候不關閉之前的場景。
還有一點很重要,LoadScene()並不是完全同步的,它只能保證在下一幀開始之前載入完畢。所以在此推薦大家使用LoadSceneAsync()這個非同步的載入方法
UnLoadScene()目前5.3中使用者只能通過Name和Build Index來同步的解除安裝一個Scene。在後續的版本中我們會提供通過Scene結構來解除安裝一個Scene,並且提供非同步解除安裝的方法。

GetActiveScene() /SetActiveScene()
獲取和設定Active scene。
GetSceneAt() / GetSceneByName() / GetSceneByPath()
查詢Scene的一組方法。
其它

EditorSceneManager

EditorSceneManager在UnityEditor.SceneManagement之下,它是Editor中的Scene Manager,提供了以下方法:
OpenScene()
它是一個同步的方法,使用者只能通過path來開啟場景。不同於LoadScene() / LoadSceneAsync(),它可以直接開啟一個存在於Assets目錄下的場景,不管它是否被新增到Build Settings
使用者可以通過OpenSceneMode來指定不同的開啟模式,相比較LoadSceneMode,它多了一個AdditiveWithoutLoading模式,允許使用者增加一個場景但並不真正載入它
CloseScene()
顧名思義,它可以關閉一個場景,同時它提供了一個bool引數來指定關閉的時候是否將場景從Scene Manager中移除。
SaveScene() / SaveScenes()
通過它們可以儲存一個或多個Scene。
MarkSceneDirty() / MarkAllScenesDirty()
通過它們可以將某個指定的場景或者所有場景標記為Dirty。大部分情況Unity內部通過Undo系統來實現場景的Dirty跟蹤,但是有些模組並沒有完全支援Undo,比如Terrain在設定某些引數的時候就不支援Undo。所以我們提供了這兩個方法支援直接將場景設定為Dirty。
API的使用限制在Editor Mode下,UnityEngine.SceneManagement.SceneManager的某些方法是不能使用的:
  • LoadScene()

  • LoadSceneAsync()

  • CreateScene()

  • UnloadScene()


同樣在Play Mode下,UnityEditor.SceneManagement.EditorSceneManager的某些方法也不能使用:
  • OpenScene()

  • NewScene()

  • CloseScene()

  • SaveScene() / SaveScenes() / …

  • MarkSceneDirty() / MarkAllScenesDirty()/…


如果使用者在不同的模式下使用了錯誤的方法,我們會在Console輸出對應的錯誤資訊引導使用者使用正確的方法。
DontDestroyOnLoad場景在Unity 5.3中,如果使用者通過Object.DontDestroyOnLoad()方法將某個Game Object標記成DontDestroyOnLoad,在進入Play Mode的時候會發現Hierarchy視窗中多出一個DontDestroyOnLoad場景,它包含了之前標記成DontDestroyOnLoad的Game Object。
為什麼需要DontDestroyOnLoad場景在Unity 5.3中,所有的Game Object必須隸屬於某一個場景。這樣我們就必須有一個特別的場景來管理這些被標記為DontDestroyOnLoad的Game Objects,否則在Unload這些Game Objects所屬的場景的時候,這些Game Objects也會被刪除掉。這顯然不是我們想要的結果。
因此我們引入了DontDestroyOnLoad場景,當進入Play Mode時候,我們會把所有標記為DontDestroyOnLoad的Game Objects從所屬的場景移入到這個特別的場景之中。
DontDestroyOnLoad場景的特點DontDestroyOnLoad場景僅僅存在於Runtime,或者是Play Mode下。它不能從外部訪問,僅僅是Unity內部用於管理標記為DontDestroyOnLoad的Game Objects。
事實上從Unity 5.3開始,我們並不推薦使用者使用DontDestroyOnLoad這一功能,它使得我們內部的程式碼邏輯複雜度增加了不少。5.3之前因為沒有多場景的支援,所以並沒有很好地辦法繞開它並實現相同的功能。而從5.3開始我們推薦使用者建立一個Manager場景,由它負責載入/解除安裝其它所有的遊戲場景。它從遊戲開始便存在一直到遊戲退出,這樣所有需要被標記為DontDestroyOnLoad的Game objects都應該屬於這個場景。
多場景編輯的進階接下來我們介紹一些關於多場景編輯的進階以及一些小技巧。

1Scene Manager Setup

Scene Manager Setup可以用來儲存並恢復當前的Scene Hierarchy。EditorSceneManager上提供了GetSceneManagerSetup() / RestoreSceneManagerSetup()來獲取和恢復Scene Hierarchy。


我們可以通過ScriptableObject來儲存Scene Hierarchy,程式碼如下所示:

以下的程式碼展示瞭如何儲存以及讀取Scene Manager Setup:

2Lightmap & NavMesh Baking

在Unity 5.3中,Lightmap和NavMesh的烘焙都同時支援多個場景,它們之間的不同之處在於如何管理和劃分烘焙的結果


對於Lightmap Baking,我們會根據Scenes劃分Lightmaps和Realtime GI資料。每個場景都只會載入和自己相關的那部分資料。
對於NavMesh Baking,因為它烘焙的結果很小,所以我們將NavMesh的資料儲存在一個asset當中,每個場景都會引用到這個asset並能夠找到自己所關聯的那部分資料。
另外使用者也可以通過指令碼進行Baking,Lightmapping.BakeMultipleScenes()和NavMeshBuilder.BuildNavMeshForMultipleScenes()都支援一次烘焙多個場景。

3Scene Dirty Track

Unity內部大多通過Undo系統來實現Scene Dirty追蹤。Unity 5.3為了支援多場景編輯,我們通過在Undo操作中儲存Scene Handles來擴充套件Undo系統。


另外我們增加了Undo.MoveGameObjectToScene()方法來支援場景之間Game Object移動的Undo。同時Scene結構上面也有一個Scene.isDirty屬性用於查詢某個Scene是否被修改。

4“Ctrl + S”的行為

在這裡有一個問題想跟大家討論的是“Ctrl + S”的行為。在5.3以前,無論場景是否Dirty,只要使用者按下”Ctrl + S”,我們一定會儲存該場景。而在5.3中,因為多場景編輯的引入,我們改變了這一行為。


從5.3開始,”Ctrl + S”只會儲存Dirty的場景。試想如果使用者打開了上百個場景,只修改了其中某一個場景,如果“Ctrl + S”還是儲存非Dirty的場景,儲存速度會受到比較大的影響。
這個改動會影響到一些Editor的工具。比如某個Editor的工具建立了一個Game Object,由於沒有使用Undo系統(Undo.RegisterCreatedObjectUndo),使得場景未標記成Dirty。這樣當在儲存的時候,Unity並不會去真正儲存這個場景。
在此推薦大家使用Undo系統來註冊Undo操作,從而能夠正確的將受影響的場景標記為Dirty。我們也樂於聽到大家的反饋,來看看我們是否有辦法更好的處理這個問題。

5Scene載入的延遲Awaking

在多場景的使用中,一個比較有意思的地方就是Scene載入過程中的Delay Awaking。在介紹它之前我們來看看Unity內部載入一個Scene所需的步驟。


6Scene載入的兩個步驟Unity內部場景的載入分為兩步:
  • Loading。是指從檔案、記憶體(主要是Streamed scene AssetBundle)中載入Scene的內容,建立並讀取所有相關的Game objects、Assets以及Scene game managers。所有的IO操作都在這一步完成,所以它是比較耗時的過程。當這一步完成的時候,我們內部會將載入進度標記為90%。

  • Awaking。主要是一些輕量級的操作,比如在Transform的Awaking的時候,我們會將Game objects加入到它所屬於的Scene。我們這裡所說的Scene載入過程中的Delay awaking就是指第二步。


比如使用者有一個大場景劃分成了若干個子場景,在所有場景載入完畢我們才會開始Game play。這時我們就可以推遲所有子場景的Awaking。當所有的載入第一步完成了,我們才進行所有場景的Awaking。

使用者可以通過將AsyncOperation.allowSceneActivation設定成false來阻止Scene的Awaking,示例如下:

當載入進度AsyncOperation.progress到達90%的時候,就可以將allowSceneActivation設定成true來允許Scene awaking。

原文連結

相關推薦

Unity場景問題以及程式DontDestory問題

Unity 5.3中新增加了多場景編輯功能,允許使用者將一個大場景以某種邏輯分割成多個小場景並方便的編輯和管理。這在某些情況下會比較有用,是對Unity編輯器對場景編輯能力的一個重要提升。 什麼是多場景編輯 多場景編輯就是允許使用者在Unity編輯器中同時開啟多個場景,並

函式內this指向的不同場景以及如何改變this的指向(bind,call,apply)

一. 對於接觸前端不太久的時候,相信會有個讓大家都感到頭疼的問題,沒錯那就是關於 this 的指向問題。我在剛接觸不久的時候也有過這樣一段時間,不過大家也不用擔心,相信大家只要把這篇部落格認真研究一遍,一定會對 this 會有一些新的認識。函式的呼叫方式決定了 this 的指

linux驅動模組開機自動載入以及應用程式開機自啟動

第一種方法:相對來說簡單 將測試程式放在/bin底下,然後用vi編輯/etc/init.d/rcS,加上/bin/應用程式名 &,加上&表示後臺執行 這兩個功能的實現都是通過設定啟動指令碼來實現的。啟動指令碼的一般存放路徑是 /etc/init.d/rc

cocos-X載入場景以及動作特效

新建一個類 newscene class newscene : public cocos2d::Layer { public:virtual bool init();static cocos2d::Scene* createScene();CREATE_FUNC(newsc

淺談Android 以及Android程式的Hello World

前言 我本是做伺服器開發,有時候工作需要和基於Android、Windows等系統進行協同開發,為了知己知彼,我花了一段時間研究了一下Android。至此, 站在一個後臺開發者的角度,總結一下Android, 以及Android和後臺的異同。 一、Android簡單概述:

關於概率分佈理論的原理分析的一些討論以及經典概率分佈的應用場景以及概率統計其在工程實踐中的應用

1. 隨機變數定義 0x1:為什麼要引入隨機變數這個數學概念 在早期的古典概率理論研究中,人們基於隨機試驗的樣本空間去研究隨機事件,也發展出了非常多輝煌的理論,包括著名的貝葉斯估計在內。 但是隨著研究的不斷深入,遇到問題的不斷複雜化,科學家們發現面對的問題也不僅僅是拋色子,口袋裡摸球、拋硬幣伯努利試驗這

unity-場景重置遊戲物件的初始化改變以及複製

1.改變遊戲物件的初始值。在指令碼之中使用Getcomponet<>()函式獲得物體的 Transform或者Rigidbody,之後呼叫隨機函式Random.range()來對遊戲物件的初始數值進行一個隨機化。並在檢測到滑鼠左鍵點選之後重置場景,之

Unity 使用C/C++ 跨平臺終極解決方式(PCiOSAndroid以及支持C/C++的平臺)

log initial ava open tis called 文章 sharp strong PC的事實上根本不用說,畢竟C#和C++交互的文章已經夠多了,當然我

Unity 使用C/C++ 跨平臺終極解決方案(PCiOSAndroid以及支持C/C++的平臺)

細節 -h comment 個人 tle lan source 多說 sharp https://blog.csdn.net/fg5823820/article/details/47865741 PC的其實根本不用說,畢竟C#和C++交互的文章已經夠多了,當然我自認為經過幾

java 強弱軟虛 四種引用以及用到的場景

優先 時間 重新 通過 如果 sof queue hashcode 等待 1、利用軟引用和弱引用解決OOM問題:用一個HashMap來保存圖片的路徑和相應圖片對象關聯的軟引用之間的映射關系,在內存不足時,JVM會自動回收這些緩存圖片對象所占用的空間,從而有效地避免了OOM的

程式設計師被裁員面試半年未果同行:都四十了還是碼農怪誰?

程式設計師真是青春飯嗎?有一名年近四十的程式設計師發帖稱:本人40歲碼農,因為年紀大被公司裁員了,海投了半年的簡歷,收到面試通知四份,都是面試完後就沒有下文了,是因為我年紀大了嗎?想當初我年輕時候找工作簡歷隨便往網上一掛,一天十多個邀請面試的電話,現在主動投遞簡歷卻無人問津。 造成程

Vuex的工作流程以及它的作用使用場景

vuex的工作流程:   1.在vue元件裡面,通過dispatch來觸發actions提交修改資料的操作。   2.然後再通過actions的commit來觸發mutations來修改資料。   3.mutations接收到commit的請求,就會自動通過Mutate來修改state(資料中心裡面

親測實驗stm32待機模式和停機模式喚醒程式的區別以及喚醒後程序入口。

這兩天研究了STM32的低功耗知識,低功耗裡主要研究的是STM32的待機模式和停機模式。讓微控制器進入的待機模式和停機模式比較容易,實驗中通過設定中斷口PA1來響應待機和停機模式。 void EXTI1_IRQHandler(void) {if(!GPIO_ReadInputDataBit(

unity】 shader的渲染次序 實現水只倒影 場景不要倒影角色。

專案裡用了個比較簡化的水(手機上用的),  角色也會倒影在很遠的水面上。 因為用了  GrabPass{"_GrabTexture"} 接取相機的資料 再做水面效果的處理。 策劃希望只過濾掉 角色的影子。 本來想換相機 設一下mask 排除角色,用相機的Re

阿里程式設計師裝逼:34歲花甲老人月薪才48k身心疲憊!

早就聽說阿里的程式設計師最愛裝逼,本來我是不信的,大企業的人怎麼會信口開河呢,看到下面我有點信了。原來阿里的大兄弟是真的很裝,不多說,但是他們說得好像也是實話,我們來看看吧。 一名阿里的程式設計師發帖說道,84年的,如今已經是34歲花甲老人,月薪只有48K,每天工作10個多小時,感覺好累,

php程式設計師的學習路線以及進階篇

# PHP interview best practices in China 如果你現在處於以下幾種狀態,本資料非常適合你: * 準備換工作,不知道從哪開始準備 * 技術遇到瓶頸,不知道該學什麼 * 準備學 PHP,但不知道領域有多深 ## 基礎篇 * 瞭解大部分陣列處理函式 * 字串處

程式設計師的辛酸猛投簡歷半年無果網友:這麼大年紀了轉行吧

程式設計師的本質有兩種:工程師和科學家。對於多數的程式設計師來說,他們是工程師。而工程師的核心競爭力在於經驗--對於工程問題來說,很多事情只要能夠解決,不管是不是有科學依據,只要解決就好了。而這一切來源於經驗。對於部分程式設計師來說,他們是科學家。科學家的核心競爭力在於總結經驗,並推廣到更加廣泛的領

模擬使用者登入場景如果連續三次輸入錯誤則退出程式

思路: 1.定義一個字串密碼,提示使用者輸入密碼 2.判斷字串密碼與使用者輸入的密碼是否一致,若一致則登入成功,跳出迴圈 3.判斷是否超過三次,若是第三次則提示三次登入失敗,退出程式 程式碼如下: #define _CRT_SECURE_NO_WARNINGS #include <st

編寫一個Java應用程式當用戶在輸入對話方塊中輸入兩個日期後(日期格式為YYYYMMDD如1999年1月12日應輸入為19990112)程式將判斷兩個日期的先後順序以及兩個日期之間的間隔天數(例

編寫一個Java應用程式,當用戶在輸入對話方塊中輸入兩個日期後(日期格式為YYYYMMDD, 如1999年1月12日應輸入為19990112), 程式將判斷兩個日期的先後順序, 以及兩個日期之間的間隔天數(例如1999年1月1日和1999年1月2日之間的間隔是1天。  

Java程式中insert 執行慢的原因以及c3p0連線池的配置

今天遇到一個問題,程式中一個insert 操作特別慢, 一直從來沒有遇到過,select 操作如果資料量大的話,是有可能出現這種情況的,但是單條insert插入操作出現這種情況,不知道從何查原因了,debug了確定了就是insert這個操作慢,一開始分析是不是mysql原因,在Navicat上ins