Unity-suli: készíts saját flippert!
Könnyedén elkészítheted az egyik legnépszerűbb játéktermi mulatság virtuális verzióját a Unityben. Szokás szerint végigvezetünk az alkotás folyamatán.
Hosszú ideje tart a flippergépek reneszánsza, némelyik tematizált asztalért nem ritkán csillagászati összegeket fizetnek a gyűjtők. Magától értetődő, hogy a videójátékok világa sem maradt sebesen cikázó, ide-oda pattogó fémgolyók nélkül; alighanem olvasóink közül is sokan gondolnak vissza nosztalgiával a Windows XP beépített Space Cadet játékára.
Régen is volt, és ma is van kereslet pinball játékokra, a hazai Zen Studios pedig a zsáner koronázatlan királya PC-n és konzolon is. Noha a cég aprólékosan kidolgozott asztalai és a golyók fizikája rengeteg munkaóra eredményét tükrözik, az alapvető mechanikákat a Unityben működésre bírni nem túlzottan bonyolult. Ha saját verziót készítenél, akkor ahhoz cikkünk lesz a legjobb kiindulópont.
Extrák nélkül
Elsősorban a Unity belső funkcióira fogsz majd támaszkodni az alkotás során, vagyis további komponensek beemelése nélkül is bátran belevághatsz a játék elkészítésébe. Indítsd el a Unity hubot, majd egy új projekt létrehozásakor válaszd a 3D-s lehetőséget. A megjelenő környezetben elsőként alkosd meg a pályaalapot szimbolizáló felületet egy kocka átalakításával. Kattints a Hierarchy alatt található Create menüpontra, és a 3D Object alatt válaszd a Cube opciót.
A kockád kijelölését követően - jobb oldalon, az Inspector fül alatt - állítsd át az objektum Scale-értékeit úgy, hogy az x legyen 20, a z pedig 30. Ha szeretnéd, mutatósabbá is teheted az imént említett felületet például úgy, hogy felállítod az oldalfalakat, de erre a lépésre később, a játékmechanika finomhangolását követően is visszatérhetsz. Hogy a pálya megfelelően lejtsen, állítsd be a megfelelő dőlésszöget is, ezzel elérheted, hogy a golyó a gravitációnak engedelmeskedve lefelé igyekezzen.
Rögzített karok
Ezek után kezdődik csak a munka oroszlánrésze, méghozzá a labda terelgetésére szolgáló karok megalkotásával és programozásával. Hozz létre a Hierarchy fül alatt található Create-tel egy kockát (3D Object/Cube), majd méretezd úgy, hogy egy karként lehessen használni (nálunk az x 4, az y és a z pedig 0,5 lett). Ha elkészültél az átalakítással, akkor illeszd a pozíciójára a kart (helyezd el valahol a pálya alsó részén), és annak érdekében, hogy elkülönüljön a pályától, adj hozzá egy új Materialt, amit színezz feketére.
Ha a kar elfoglalta a pozícióját, akkor a következő lépésként a tulajdonságait tartalmazó Inspector fül alatt kattints az Add Component gombra, és a keresőmezőbe gépeld be a Hinge Joint opciót, ezzel a tulajdonsággal tudod majd megfelelően rögzíteni az "ütődet". Emellett szükséged lesz még a komponenst különféle fizikai hatásokkal felruházó Rigidbodyra is, ezt szintén az előzőleg használt Add Componenttel társíthatod.
A Hinge Joint információit tartalmazó Inspector-felületnél keresd meg az Anchor tulajdonságot, majd itt az x-et állítsd 0,5-re, a többi pedig legyen lenullázva. Az Axishoz tartozzék egy felfelé mutató vektor, ezért az y-nak adj 1-es értéket. A beállításokkal nagyjából megvagyunk, áttérhetünk a kódolásra.
Életre keltett ütők
A lent található Project fül alatt klikkelj a Create gombra, majd a felugró menüből válaszd a C# Script lehetőséget, a fájlodnak pedig add a pinBallHandle nevet. Ezt követően nyisd meg az üres kódot valamilyen szerkesztőalkalmazással, és hozz létre négy változót a kar tulajdonságainak kezelésére (public float rest=0f; public float pressed=-45f; public float hit=10000f; public float dmp=150f;), egyet a csatlakozópont kóddal történő manipulálására (HingeJoint hingeP;), egyet pedig a bemeneti gombok ellenőrzésére (public string inputs;). Ha végeztél, a Start függvény belsejében használd a hingeP=GetComponent<HingeJoint>(); valamint a hingeP.useSpring = true; kódokat a "zsanér" konfigurálásához.
Majd lépj át az Update()-be, és a JointSpring spring = new JointSpring(); spring.spring = hit; spring.damper=dmp; kóddal folytasd a beállításokat, és egy feltételben vizsgáld az esetleges beérkező gombnyomásokat, hogy ez alapján módosítani tudd a kar állását (if(Input.GetAxis(inputs)==1){ spring.targetPosition= pressed;}else{spring.targetPosition= rest;}). Végezetül az eredeti csatlakozási pontra vezesd át a módosításokat (hingeP.spring = spring; hingeP.useLimits=true;).
A vezérlőkód tehát kész, a teszteléshez már csak annyi a teendőd, hogy csatolod a karhoz, és a tulajdonságainál a Hinge Joint Use Limits értékét aktiválod, a minimumot pedig beállítod -45-re. A kód tulajdonságai lehetővé teszik, hogy egyedi billentyűket társíts a karok kezeléséhez, de ha csupán annyit írsz ide, hogy Fire1, akkor a bal oldali Ctrl-gomb, valamint az egered bal klikkje is aktiválja az ütőt. Ha a tesztelés során úgy tapasztalod, hogy rendeltetésszerűen működik a kar, akkor készíthetsz is egy másolatot belőle a Ctrl+D billentyűkombinációval.
Forgatásokkal helyezd el a kiszemelt pozícióba ezt a játékelemet is, majd a tulajdonságainál a Limits és a Pressd -45-ös értéke elől tüntesd el a negatív előjelet, valamint a Fire1-et írd át Fire2-re, és már kész is a második vezérelhető komponensed. Dobj a jelenetbe egy labdát (Create/3D Object/Sphere), ehhez csatolj egy Rigidbody komponenst, és már ki is próbálhatod az ütők működését.
Kilövésre fel!
Most, hogy az alapok készen állnak, és a karok is megfelelően működnek, már csak a golyó kilövését kell megoldanod. Ha eddig még nem tetted meg, készíts egy keretet a pálya köré, majd a jobb oldali falat duplikálva és némileg megkurtítva hozz létre egy indítócsatornát, ami csak minimálisan legyen szélesebb a labda méreténél. Ezek után a pálya alsó falába ékelj egy hengert (Create/3D Object/Cylinder), ezt érintve a golyód azonnal kilő majd, igaz, a sikeres indításhoz némi szkriptelés is kelleni fog.
Hozz létre egy új C#-kódot, majd a felületén az OnCollisionEnter (Collision other){} metódussal ellenőrizd az ütközést. Mivel ebbe a csatornába valószínűleg egyetlen másik játékkomponens se kerül be, annyi csak a dolgod, hogy ütközéskor egy erőhatással útjára indítod a hengerhez érő objektumot (float magnitude = 1000f; Vector3 force = transform.position - other.transform.position; force.Normalize(); other.gameObject.GetComponent<Rigidbody>().AddForce(-force * magnitude);).
Az erőhatás mértékét érdemes a tapasztalatok alapján meghatározni: ha túlzottan erősen lőne ki a golyó, akkor bátran csökkentsd, ha pedig nem jut el a pályáig, akkor nyugodtan növeld a magnitude referenciaértékét. A golyót helyezd az indítócsőbe, kevéssel a henger pozíciója fölé, az indítást követően a labda rágurul a kilövőre, és elindul a pályád felé.
Így fejleszd tovább!
Rengeteg úton elindulhatsz, ha többet is kihoznál kezdetleges flipperedből. Amennyiben rendelkezel némi modellezői vénával, megpróbálhatod egy külső alkalmazásban kidolgozni a pályát és annak egyes elemeit, majd ezt a Unitybe átemelve a cikkben szereplő kód segítségével már egyszerűen életre keltheted (akkor se aggódj, ha nem boldogulsz a 3D-modellező szoftverekkel, némi keresést követően találhatsz kész, azonnal bevethető alkotásokat is).
Érdemes lehet még gondoskodni a pontok számlálásáról, ehhez helyezz el különféle ütközőket a pályaalapon (egyszerű hengerek is megteszik). Néhány sornyi kóddal pedig azt is elérheted, hogy a pálya alsó falának érintését követően ismételten a kilövőbe kerüljön a golyó. Hogy segítsünk az első lépések megtételében, a PC World Pluson elhelyeztünk egy szkriptet, amelynek jó hasznát veszed a pontszámításban és a golyó "teleportálásában".