A field
A field vagy mező egy változó, ami nem metódusban, hanem pusztán osztályon belül lett deklarálva. A field minden objektum orientált programozási nyelvben megtalálható eszköz. Ez azt jelenti, hogy a mező nem csak MonoBehaviour osztályokban létező fogalom, ám most csak ebben a kontextusban fogjuk tárgyalni.
Itt tanulunk majd róla részletesen: Összetett típusok és példányaik, Változók, tagok és a this kulcsszó
A mező vagy más néven field változók összessége tárolja egy adott Unity MonoBehaviour szkript-hez kötődő információkat minden egyes példányra. A Scene-ben elhelyezett megfelelő típusú komponensek mindegyike tartalmazni fogja ezeket a változókat külön-külön és példányonként egyedi értékük megörződik mindaddig, amíg a komponens maga is létezik.
Ezen Field-eket fogjuk használni arra, hogy hosszútávon eltároljuk bennük egy adott MonoBehaviour komponens példányának beállításait valamint a mindenkori aktuális állapotát.
Vegyünk egy példást!
Képzeljük el, hogy van egy MonoBehaviour szkriptünk, ami egy ellenfelet (Enemy
) reprezentál. Ennek az ellenfélnek van egy maximum élet beállítása (maximumHP
) és egy aktuális, jelenlegi életszáma (currentHP
), ami futás közben minden ellenfélre változhat.
Ezek közül mindkettőt egy int
típusú mezőben fogom eltárolni az Ellenfél szkriptben. Minden egyes ellenfélnek ekkor külön be lehet állítani a maximális életét és minden egyes ellenfélnek létezik egy saját pillanatnyi élete, ami időben változik.
public class Enemy : MonoBehaviour
{
int maxHP = 100; // Field - Beállítás
int currentHP; // Field - Aktuális időben változó állapot
void Start()
{
currentHP = maxHP;
}
}
Az életszámnak nincs értelme egy konkrét ellenfél példány nélkül és fordítva, az ellenfél értelmezhetetlen élet nélkül. Az ellenfél objektum és az ő mezői tehát szorosan összekapcsolódnak. A field-ek összessége jelenti egy adott komponens mindenkori aktuális állapotát.
Egy komponens beállítása: A SerializeField attribútum
Az attribútumok lehetőséget biztosítanak arra, hogy olyan programozási elemeket, mint típusok, mezők és metódusok, stb. kiegészítő információkkal ruházzunk fel.
Főleg arra a célra lettek az attribútumok megalkotva, hogy kiegészítsék a C# nyel funkcionalitását olyan keretrendszerek számára, mint a Unity, ami hozzá tud férni ezekhez a kiegészítő információkhoz és működését ehhez mérten tudja módosítani.
Egy attribútumnak mindig adott, hogy miféle programozási elemek-hez rendelhető.
(Egy programozási elem attribútumait és egyéb tulajdonságait úgy nevezett Reflexió segítségével lehet elérni. Attribútumok írásával és lekérésével most nem foglalkozunk csak a Unit által készítetteket fogjuk használni.)
Az attribútumokat szögletes zárójel közé írjuk.
Az attribútumokról bővebben itt olvashatsz: Hasznos Unity attribútumok
Most meg fogunk tanulni egy kizárólag Unity specifikus attribútumot, a szerializált mezőt.
Egyelőre ne foglalkozzunk azzal, mi az, hogy szerializálás, csak nézzük meg mi történik akkor ha egy field elé a [SerializeField]
attribútumot írjuk!
using UnityEngine;
class SerializeFieldTest : MonoBehaviour
{
[SerializeField] string myName; // Név
[SerializeField] int age; // Életkor
[SerializeField] float height; // Magasság
[SerializeField] bool isSmoking; // Dohányzik-e
void Start()
{
string introduction = $"My name is {myName}. " +
$"I'm {age} years old and {height} m height. " +
$"Do I smoke? {isSmoking}.";
// A nevem ....
// ... éves és ... m magas vagyok.
// Dohányzom-e? .....
Debug.Log(introduction); // Kiíratás
}
}
A fenti kód hatására így fog kinézni a Unity komponensünk az Inspector ablakban:
Ekkor bármilyen értéket manuálisan beállíthatunk a megfelelő mezőknek a Unity felhasználói felületén keresztül.
A kitöltött adatok a Scene file-ba kerülnek mentésre. (Egyelőre…)
Tehát minden olyan mezőre, ami [SerializeField]
tekinthetünk úgy, mint az adott komponens egy beállítására.
[SerializeField]
változók által tudunk beállításokat hozzárendelni egy komponenshez.Képzeljük el, hogy egy komponens, azért felel, hogy a billentyűk lenyomására mozgassa a karakterünket. Így tudnánk olyan paramétereket megadni, hogy mekkora legyen a játékos gyorsulása, maximum sebessége vagy hogy melyik gombok hatására mozogjon.
Egyéb attribútumokat is írhatunk szerializált változók elé hogy módosítsuk kicsikét a megjelenítésüket vagy viselkedésüket.
[Space]
- Rövid szünet
[Min( 0 )]
- Megadhatunk egy minumum értéket egy int vagy float számnak. (Jelen példában: 0)
[Range( 1, 10 )]
- Megadhatunk egy minimum és egy maximum értéket egy int vagy float számnak. (Jelen példában minimum érték: 1 és maximum érték: 10)
Ha több attribútumot szeretnénk egy field-hez rendelni, akkor azt két módon tehetjük meg:
[SerializeField] [Space] [Min(0)] int n1; // Külön szögletes zárójelben.
[SerializeField, Range(0,1)] float n2; // Egy zárójelen belül, vesszővel elválasztva
A két fenti módszer csak szintaktikában tér el. Egyébként pontosan ugyanazt jelenti.
A szerializáció
Mikor a [SerializeField]
attribútumot írjuk egy mező elé, akkor gyakorlatilag azt mondjuk ki, hogy “Ez a field legyen szerializált!” Na de mi a fene az, hogy valami szerializált?
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á.
A Unity a Scene-ben tárolt adatokat szerializálja és elmenti fájlba. Egy MonoBehaviour komponensnek azon field-jei kerülnek automatikusan szerializálásra, amiket megjelöltünk a [SerializeField]
attribútummal.
(Nem csak Scene de Prefab és ScriptableObject is szerializálható. Ezekről később…) Prefab-ok, ScriptableObject
Ezt a mentett fájlt tölti be a Unity, amikor elindul egy Scene az Editor-ban vagy a végleges játékban. A fájl betöltésével létrehozza a motor a szükséges GameObject-eket és azok komponenseit valamint beállítja ezen komponensek szerializált mezőit.
[SerializeField]
attribútummal a gyakorlatban azt mondjuk ki egy mezőről, hogy ez egy beállítás, amit manuálisan az Unity Editor Inspector felületén lehet majd megadni.Szóval vegyük át még egyszer!
Ha egy MonoBehaviour field-je (mezője / tagváltozója) elé a [SerializeField]
attribútumot írjuk, akkor a field
- egyfelől megjelenik a Unity Inspector felületén és az értéket ott, az Editorban tudjuk állítani,
- másfelől a Scene file-ban mentésre kerül a beállított érték és ha újra betöltjük a Scene-t, akkor a beállítás megmarad.
Nem szerializált mezők
Fontos kiemelni, hogy nem csak [SerializeField]
mezőket érdemes használni Unity-ben. A nem szerializált mezőknek is ugyanúgy megvan a haszna. Ezek fogják eltárolni egy szkriptelt komponens mindenkori aktuális állapotát.
Public és [SerializeField] mezők - Kiegészítő anyag
Az alábbiak megértéséhez szükséges a Tagváltozók és -metódusok láthatósága lecke megértése:
A Unity minden publikus mezőt úgy kezel, mintha a [SerializeField]
attribútum elé lenne írva akkor is, ha ezt nem tesszük meg. Tehát a publikus field-ek anélkül is megjelennek az Inspector-on és mentődnek, hogy ezt külön jeleznénk.
Fontos kiemelni, hogy a publikus és [SerializeField]
mezők nem pontosan ugyanúgy működnek, ugyanis privát, de változókat az osztályon kívül továbbra sem tudunk kódból elérni.
public
mező [SerializeField]
, de nem minden .Szerializálható típusok - Kiegészítő anyag
Nem minden típust lehet Unity-ben szerializálni és ezáltal beállításként használni.
Az alábbi felsorolás a szerializálható típusokat veszi számba:
int number1; // Minden C# beépített primitív típust
float number2;
bool bit;
string text;
//...
Vector2 vercor2; // Több Unity adat típust
Vector3 vercor3; // (Ezeket később tanuljuk majd...)
Rect rect;
Bounds bounds;
Color color;
Gradient gradient;
AnimationCurve curve;
//...
GameObject gameObj; // GameObject referenciákat
Camera camera; // Bármilyen komponens referenciát
SpriteRenderer rend;
//...
MyMonoBechaviour custom; // Beleértve saját MonoBechaviour szkriptet
MyScriptableObj scrObj; // ScriptableObject referenciák (Később tanuljuk...)
//...
Direction dir; // Tetszőleges enum-ot
enum Direction
{
North, South,
East, West
}
MyPerson person; // Tetszőleges saját osztályt vagy struktúrát,
[Sysetm.Serializable] // amit ellátunk a [Sysetm.Serializable] attribútummal
class MyPerson
{
public string name; // Ezentípusok field-jei is szerializáltak kell, hogy legyenek
public int age; // Ezt itt most a public kulcsszóval értem el.
}
int[] number; // Tetszőleges Szerializálható típus tömbje
List<Collider> colliders; // Tetszőleges Szerializálható típus listája
// NEM lehet viszont egymásba ágyazott
// sorozatot (tömb vagy list) szerializálni
// Nem tettem most ki minden field elé a [SerializeField] attribútumot
// vagy a public kulcsszó, de ez mindenképp veltétele a szerializációnak.