A legnagyobb alapegysége egy Unity szoftvernek a jelenet vagy Scene.
Egy jelenet tetszőleges számú GameObject-et tartalmazhat és ezen Scene-ek külön fájlokban kerülnek eltárolásra. A Scene fájlok tartalmazzák a bennük lévő összes GameObject és azok komponenseinek minden szerializált tulajdonságát.
Bővebben: Unity Engine alapjai és logikája
A szerializáció az a folyamat, amikor egy programozási objektumból nyelv- és platformfüggetlen adatot készítünk.
Ezt a szerializált adatott aztán többek között elmenthetjük fájlba vagy továbbíthatjuk hálózaton keresztül.
A szerializált adatokat később deszerializálás során lehet visszaállítani az eredeti formájukra, azaz programozási nyelvek objektumaivá.
Új Scene-t létrehozni hasonlóan lehet mint bármely egyéb Asset fájlt:
- Jobb katt egy mappán belül / Create / Scene
- vagy Felső menüsáv / Assets / Create / Scene
A betöltött jelenet (vagy jelenetek) az azonos nevű Scene ablakban láthatóak, mint legördülő (kinyitható) faszerkezet.
Több Scene egyszerre
Egy Unity programban mindig legalább egy Scene be van töltve, ám a motor megengedi, hogy egyszerre több jelenet is betöltött állapotban legyen egymás mellett. Ebben az esetben a különböző Scene-ek GameObject-jei egymás mellett léteznek, mintha egy jelenetben lennének.
Kétfajta módin tudunk tehát betölteni egy jelenetet:
- Betöltés / Felülíró betöltés: Egy korábban betöltött Scene teljes lecserélése egy újabbra.
- Additív betöltés / hozzáadó betöltés: Hozzáadunk egy új Scenet, úgy hogy az eddigiekhez azok kitöltése nélkül.
Ha duplán kattintunk Unity Editor-ban egy Scene fájlra, akkor a kiválasztott Scene betöltésre kerül míg a korábban betöltöttek törlődnek a listából. (Felülíró betöltés)
Viszont ha Editoron belül egyszerre több Scene-t is szeretnénk betölteni, akkor az új Scene-eket (, azaz az eddigiekhez hozzáadva betöltendő Scene-eket) Drag’n Drop módszerrel kell a Scene ablakra húzni. (Additív betöltés)
Kitölteni vagy Unload-olni egy Scene-t az Editor-ban úgy lehet, hogy jobb gombbal rákattintunk és az Unload lehetőséget választjuk. Ez persze csak abban az esetben lehetséges, ha egynél több jelenet volt betöltve.
Ebben az esetben a Scene nem tűnik el a listából, ehhez a Remove lehetőséget kell választanunk.
(Megemlítendő, hogy ezen unload-olt Scene-ek a játék indításakor nem lesznek jelen semmilyen formában. Az hogy a Scene alablak listájában megjelenhetnek kitöltött Scene-ek is az csak egy fejlesztői segédeszköz. Ilyen helyzetet csak Play módon kívül lehet elérni.)
Aktív Scene
Több egyszerre betöltött jelenet esetén mindig van egy kiemelt szerepű, ezt Aktív Scene-nek nevezzük. Az aktív Scene-ek tulajdonságai:
- Ha új GameObjectet hozunk létre és nem adunk meg neki szülő GameObject-et, akkr az automatikusan az aktív Scene-be kerül.
- Az aktív Scene-hez tartozóm render (képszintézis) beállítások lesznek érvényesek.
- Az aktív Scene-hez tartozóm lighting (fényelési) beállítások lesznek érvényesek.
- Az aktív Scene-hez tartozóm navigációs beállítások lesznek érvényesek.
Editorban az aktív Scene neve vastag betűvel szedett.
Scene-ek betöltése kódból
Az eddigiekben csak arról beszéltünk, az Unity Editorban hogyan lehet váltogatni a Scene-ek közt manuálisan. Most nézzük meg mi történik Play módban és a játék végleges Buildelt verziójában.
Ezután kódból kell gondoskodnunk arról, hogy felülíró vagy additív módon betöltsünk egyéb Scene-eket.
A Buildben szereplő jelenetek beállítása a következőképp érhető el:
Felső menüsáv / File / Build Settings / Scenes in Build
Bővebben: Játék Build-elése (Hamarosan)
Ha nem így teszünk, akkor Editoron belül csak Warning üzenetet kapunk, ám build-ben egyszerűen nem fog megtörténni a betöltés, hiszen a build fájlok nem is fogják tartalmazni a szükséges adatokat.
Scene-ek menedzseléséhez használni kell a UnityEngine.SceneManagement névteret és azon belül a SceneManager osztályainak különböző statikus metódusait:
using UnityEngine.SceneManagement; // Megfelelő névtér használata a fileban
...
// Egy Scene-re kétféleképp tudunk hivatkozni:
// - a file nevével:
SceneManager.LoadScene("Example1"); // Az Examnple1 nevű Scene felülíró betöltése
// - a build beállítások jelenet listájában szereplő indexével:
SceneManager.LoadScene(1) // Az 1-es indexű Scene felülíró betöltése
// Opcionális paraméterrel megadható, hogy a betöltés felülíró vagy additív legyen:
SceneManager.LoadScene("Example2", LoadSceneMode.Single); // Felülíró betöltés
SceneManager.LoadScene(2, LoadSceneMode.Single); // Felülíró betöltés
SceneManager.LoadScene("Example3", LoadSceneMode.Additive); // Additív betöltés
SceneManager.LoadScene(3, LoadSceneMode.Additive); // Additív betöltés
Scene-ek felülíró betöltését használhatjuk például arra, hogy váltsunk különböző pályák vagy a főmenü és a játék között, de arra is hogy újra töltsünk egy már betöltött Scene-t az eredeti állapotára, ezzel gyakorlatilag újraindítva a játékot.
Aszinkron be- és kitöltés
Ha az Async
szó szerepel a metódus nevében az azt jelenti, hogy a betöltést / kitöltést egy külön operációs rendszer szálon fogja végezni a játékmotor, ennek a következő a hatása:
NEM aszinkron betöltés: A játék futása megakad, addig amíg a betöltés nem végzett.
Aszinkron betöltés: A játék akadás nélkül fut tovább, addig amíg a betöltés nem végzett.
Aszinkron jelenetbetöltés indítása:
// Felülíró aszinkron betöltés:
SceneManager.LoadSceneAsync("Example1"); // Az Examnple1 nevű Scene betöltése
SceneManager.LoadSceneAsync(1) // Az 1-es indexű Scene betöltése
// Additív aszinkron betöltés:
SceneManager.LoadSceneAsync("Example2", LoadSceneMode.Additive) // Examnple2 betöltése
SceneManager.LoadSceneAsync(2, LoadSceneMode.Additive) // A 2-es indexű Scene betöltése
Aszinkron jelenet be- és kitöltés esetén egy esemény jelzi azt, hogy mikor végzett a folyamat. Ha valami saját kódot szeretnénk futtatni ekkor, “feliratkozhatunk” erre az eseményre. Bővebben: Esemény-vezérelt programozás (Hamarosan)
Jelenetek kitöltése csakis aszinkron módon javasolt:
SceneManager.UnloadSceneAsync("Example1"); // Az Examnple1 nevű Scene kitöltése
SceneManager.UnloadSceneAsync(1); // Az 1-es indexű Scene kitöltése
SceneManager.UnloadScene("Example1"); // Működik, de nem javasolt: Akkadást eredményez
SceneManager.UnloadScene(1);
Néhány egyéb hasznos SceneManager metódus:
// Scene objetum létrehozása
Scene scene1 = SceneManager.GetSceneByName("Example1");
Scene scene2 = SceneManager.GetSceneByBuildIndex(2);
Scene activeScene = SceneManager.GetActiveScene(); // Mi az aktív Scene?
SceneManager.SetActiveScene(scene1); // Ez legyen az aktív Scene!
Scene[] allScenes = SceneManager.GetAllScenes(); // Összes betöltött Scene lekérdezlése
DontDestroyOnLoad
Érdemes külön GameObject-et és külön komponenst létrehozni arra, hogy a játékunk jeleneteinek be- és kitöltését vezényelje.
Ezt a GameObject-et javasolt a “DontDestroyOnLoad” kategóriába tenni, azaz elérni, hogy Scene-ek ki és betöltésekor ne törlődjön. Ezt a következő módon lehet megtenni:
void Start() // Érdemes egyből a Start metódusban elintézni
{
DontDestroyThisOnLoad(gameObject);
}
Ezt a műveletet más objektumokkal is érdemes lehet megtenni, ha azt szeretnénk, hogy azok a szoftverünk teljes futása alatt létezzenek.
Bővebben: Komponensek hierarchiája
Ez egy ideális módszer arra, hogy a futó játékunk bizonyos információit átmentsük különböző Scene-ek betöltése közt.
(Erre egyébként használhatók statikus változók is: Statikus tagok és osztályok)