Már sok gizmót láttunk a Unity-ben. Általában csak annyit mondhatunk el egy gizmóról, hogy az valami olyasmi, amit a fejlesztő lát, de a felhasználó (játékos) nem.
Ezek szolgálhatnak arra, hogy pusztán csak valami rejtett beállítást a fejlesztőnek, például egy pozíciót vagy irányt. Ám olyan gizmók is vannak, amikkel interakcióba lehet lépni. Általuk akár módosíthatjuk is egyes komponensek bizonyos beállításait:
Mi is írhatunk gizmókat a saját komponenseinkhez. Ehhez a OnDrawGizmos()
és OnDrawGizmosSelected()
elnevezésű MonoBehaviour üzenetmetódusokat fogjuk használni.
Ezeket az eljárásokat játékmotor a Start()
-hoz, Update()
-hez és az OnValidate()
-hez hasonlóan automatikusan fogja hívni minden olyan komponensre, ami szerepel a scene-ben.
void OnDrawGizmos()
{
// Egy 1 sugarú gömböt rajzolok a GameObject pozíciójába. ami mindig látszik
Gizmos.DrawWireSphere(transform.position, 1f);
}
void OnDrawGizmosSelected()
{
// Ez a gömb nagyobb (2 sugarú) és csak akkor látszik, ha az objektum ki van jelölve:
Gizmos.DrawWireSphere(transform.position, 2f);
}
Ahogy a videón is látható a nagyobbik gömb csak akkor látszik, ha a megfelelő GameObject ki van jelölve, mivel annak kirajzolása OnDrawGizmosSelected()
-ben történt.
Fejlesztés alatt a Unity Editorban gizmókat a Game és a Scene ablakokba is kirajzolhatunk. Mindkettő beállításaira az adott alablak fejlécében van lehetőség.
Fontos megjegyezni azonban, hogy a végleges játékban sosem fog látszani semelyik gizmó. A gizmók teljese egészében fejlesztői eszközök, amik a programozók és GameDesigner-ek munkáját segítik és a felhasználó sosem találkozik velük.
Nagyon sok mindenre használhatunk gizmókat. Kirajzolható vele például egy mozgó tárgy mozgásvektora, egy sebezhető objektum élete vagy egy ellenfél látótávolsága, hogy csak néhányat említsek. A jövőben fogjuk is használni a gizmó-rajzolást több esetben is.
A Color típus
Több színnel is tudunk rajzolni. Ehhez a Color típust fogjuk használni.
[SerializeField] Color drawingColor;
void OnDrawGizmos()
{
Gizmos.color = drawingColor; // Rajzoló szín beállítása
Gizmos.DrawWireSphere(transform.position, 1f); // Rajzolás
}
Egy szín mindig 3+1 csatornából áll: Vörös, Zöld, Kék és Alfa azaz Red, Green, Blue és Alpha.
Minden csatorna egy számérték vagy 0 és 255 (editorban) vagy 0 és 1 (kódban) közt.
Az alfa csatorna, más néven opacitás vagy átlátszatlanság szabályozza mennyire áttetsző színnel rajzolunk.
Magunk is létre tudunk hozni új színeket, de le is tudunk kérdezni pár előre elkészített alapszínt:
Color transparent = new Color(); // default érték: 0,0,0,0 (fehér, átlátszó)
Color black = new Color(0, 0, 0, 1); // fekete, teljesen átlátszatlan
// Mindig minden r, g, b, a érték 0 és 1 között legyen.
Color red = Color.red; // piros színt le tudjuk kérni
Color red2 = new Color(1, 0, 0, 1); // de magunk is létrehozhatjuk
Color green = Color.green;
Color white = Color.white;
Color yellow = new Color(1, 1, 0, 1);
float brightness = 0.75f; // Világosság
Color gray = new Color(brightness, brightness, brightness, 1);
Gizmó rajzoló függvények
Íme néhány gizmó rajzoló függvény:
[SerializeField] Transform t1, t2, t3, t4, t5, t6; // Pozíciók
[SerializeField] Color c1, c2, c3, c4, c5; // Színek
void OnDrawGizmos()
{
Gizmos.color = c1;
Gizmos.DrawWireSphere(t1.position, 0.75f); // Drótgömb
Gizmos.color = c2;
Gizmos.DrawWireCube(t2.position, Vector3.one); // Drótkocka
Gizmos.color = c3;
Gizmos.DrawSphere(t3.position, 0.75f); // Feltöltött gömb
Gizmos.color = c4;
Gizmos.DrawCube(t4.position, Vector3.one); // Feltöltött kocka
Gizmos.color = c5;
Gizmos.DrawLine(t5.position, t6.position); // Vonal két pont között
// És még sok más...
}
Gizók rajzolása OnDrawGizmos metóduson kívülről
A Gizmó rajzolás kényelmetlensége, hogy csak OnDrawGizmos
és OnDrawGismosSelected
metóduson belülről működik. Ha kifejezetten vonalat szeretnénk rajzolni, akkor használható a Debug.DrawLine
és a Debug.DrawRay
metódusok, amik bárhonnan hívhatók.
Vector3 pos = transform.position;
Vector3 forward = transform.forward;
// Parméterek:
Debug.DrawRay(pos, forward); // Honnan? Milyen irányba?
Debug.DrawLine(pos,pos + forward); // Honnan? Hova?
Mindkét metódusnak van 3 opocionális paramétere a következő alapértelmezett értékekkel a megfelelő sorrendben:
Color color = Color.white // Milyne színnel rajzoljunk?
float duration = 0.0f // Hány másodpercig látszódjon a vonal?
bool depthTest = true // A kamerától távolodva halványuljon-e?
Sok esetben egyszerűbb lehet ezekkel dolgozni, hisz bárhonnan hívhatók, ám ne feledjük, hogy nem minden metódus hívódik meg folyamatosan, pláne nem Play módon kívül. Ezért ha például Update
-ben használjuk a Debug.DrawLine
és a Debug.DrawRay
metódusokat, akkor ez eredmény csak futás közben, Play módban fog látszani.
Rajzolás lokális koordinátarendszerben
Figyeljük meg, hogy eddig mindig a globális koordinátarendszerben rajzoltunk, tehát a kirajzolt gizmónk nem függött közvetlenül a az objektum pozíciójától és orientációjától, ami kirajzolta azt.
Úgy tudtunk az objektum pozíciójába rajzolni, ha megmonduk, hogy az objektum hol vana globális térben: pl.: Gizmos.DrawWireSphere(transform.position, 1f);
Ha saját koordinátarendszerben szeretnénk rajzolni, azt a következő módon tudjuk megtenni.
Gizmos.matrix = transform.localToWorldMatrix; // Rajzoljunk saját koordinátarendszerbe
// Rajzolás lokális térben
Gizmos.DrawWireSphere(Vector3.zero, 0.11f);
// ...
Gizmos.matrix = Matrix4x4.identity; // Rajzoljunk újra globális koordinátarendszerbe
Ezt úgy értük el, hogy átírtuk, hogy a Unity milyen transzformációs mátrixot használja a gizmo rajzoláshoz. Ennek elméletével később foglalkozunk: Transzformációs mátrixok (Hamarosan) Egyelőre elég annyit megjegyezni, hogyan kell végrehajtani ez.
A lokálist térben való rajzolás sok esetben sokkal könnyebb, mint globális térben. Tegyük fel például, hogy az objektum lokális síkjában akarok egy vízszintes négyzetet kirajzolni. Ezt könnyen megtehetjük a következő módon:
// Rajzoljunk saját koordinátarendszerbe
Gizmos.matrix = transform.localToWorldMatrix;
// Négyzet sarkai
Vector3 p1 = new(-1, 0, -1);
Vector3 p2 = new(1, 0, -1);
Vector3 p3 = new(1, 0, 1);
Vector3 p4 = new(-1, 0, 1);
// Négyzet oldalai:
Gizmos.DrawLine(p1, p2);
Gizmos.DrawLine(p2, p3);
Gizmos.DrawLine(p3, p4);
Gizmos.DrawLine(p4, p1);
Figyeljük meg, hogy milyen egyszerűen tudtuk felvenni a négyzet sarkainak pozícióit. Csak a 0, 1 és -1 számokat használtuk és az eredmény mégis az, hogy a kirajzolt négyzet követi a kirajzoló objektum pozícióját, rotációját és skálázását.
Ha ezeket a sarokpontokat manuálisan szerettük volna kiszámolni, akkor mind a négy pontot egyenként át kellett volna transzformálni globális kooordinátarendszerbe a Transform.TransformPoint()
függvénnyel. Bővebben: A lokális és globális tér