Jelen lecke tekinthető GameObject-ek azonosítása című fejezet folytatásának. Java
A név szerint történő keresés és azonosítás problémája, hogy felesleges redundanciát hoz be a projectbe és ezáltal törékenyebbé teszi azt, a szükségesnél.
Egy objektum neve legalább két helyen lesz így jelen a projektben: Egyszer az editorban és egyszer a kódban. Itt a redundancia. Ezek közül bármelyiket írja át a fejlesztő, az hibás működéshez vezet. És ami még rosszabb, ezt a hibát nem is garantált, hogy hamar észrevesszük.
Ez talán nem hat nagy gondnak, akkor érzi át igazán a fejlesztő a probléma súlyát, amikor egy bizonyos méreten túllép a projekt. Ekkor eljuthat a fejlesztés arra a pontra, amikor senki nem mer semmit átnevezni mert attól fér, hogy az valahol szerepel a kódban és eltör vele valamit.
Megoldás lehet, hogy minden átnevezés előtt mindenki rákeres a kódban az adott névre. Ez azonban csak egy csúnya és lassú megkerülése a problémának. Nem beszélve arról, hogy a projekten dolgozhatnak dizájnerek is, akik nem jártasak a kódszerkesztésben.
Amit most leírtam egy esernyőprobléma, ami nem korlátozódik csak a GameObject-ek nevére. A Unity-ben több esetben is név szerint kell vagy lehet hivatkozni programozási elemekre és ezen string összehasonlítások mindegyikével ugyanaz a gond, mint amit előbb leírtam:
- GameObject.Find(”GameObject neve”);
- Invoke(”Metódus neve”);
- UI elemek név szerint hívnak metódusokat
- Animációs eventek név szerint hívnak metódusokat
- Tag-ek
- LayerMask.NameToLayer
- GUI és EditorGUI metódusok paramétereiben név szerint kell hivatkozni más metódusokra
- …
Megoldási lehetőségek
- Használhatunk név vagy tag-ek lekérdezése helyett komponens lekérdezést.
- Lehetséges, létrehozni egy ScriptableObject típust csak arra a célra, hogy vele azonosítsunk GameObject-eket. Ekkor külön komponenst, kell létrehozni, azért hogy a fenti ScriptableObject-ekkel be tudjunk jelölni egy GameObject-et.
- Nem string összehasonlításon alapul: stabilabb
- Több tag is hozzárendelhető egy GameObject-hez
- Ha később szeretnénk, akkor beállítások is adhatók az összes vagy bizonyos tag-ekhez. (Lehet, hogy le kell ehhez származnia Tag osztályból.)
- Sokkal gyorsabb
- A C# 6.0 verziótól kezdődően a nyelv része a
nameof()
, amivel lekérdezhető egy programozási elem neve string-ben. Ez sok esetben teljesen megoldja a gondunkat. - Eseményvezérelt architektúra használata
SomeMonoBehaviour component = FindObjectOfType<SomeMonoBehaviour >();
Ekkor akár azért is létrehozhatunk egy MonoBehaviour komponenst, hogy azt mint afféle azonosítót hozzáadhassuk egy vagy több GameObject-hez.
Ám erre legtöbbször nincs szükség. Gyakran van egy konkrét komponens, amit keresünk.
Ezzel a rendszerrel leválthatjuk teljesen a Unity tag rendszert, ami kizárólag névösszehasonlításon alapul. A mi rendszerünk előnyei:
void Start()
{
Invoke(nameof(Destroy), 2.5f);
}
Például UI gombok lenyomására kódból iratkozunk fel és nem az editor felületen.
Hol nem tudjuk kikerülni a string összehasonlítást?
Eddigi tapasztalataim szerint egyedül az animáció kapcsán nem tudjuk megkerülni, hogy string-ek által azonosítsunk programozási elemeket.
- Animációnál név szerint hivatkozunk a módosítandó paraméterekre
- Animációs paraméterekre kódból névvel kell hivatkozni.
- Animációs események név szerint hivatkoznak meghívandó metódusokra.