What a Wonderful World

A Unity rengeteg lehetőséget és szabaságot nyújt, így a legtöbb gondott nem is a játék megírása okozza, hanem annak a kitalálása, hogy hogy kezdjünk hozzá…

Kiskoromban rengeteg LEGO-szettem volt – imádtam építeni, mindig valami újat kitalálni. Jóformán meg is rökönyödtem, amikor két anyuka beszélgetését hallgattam a trolin:

– Ricsinek állandóan LEGO-t kell venni, alig bírjuk pénzzel… De legalább nagyon szereti: a múltkor egy kalózhajót épített át űrhajóvá.
– Petinek nem érdemes: egyszer kirakja az útmutató szerint, aztán porosodik a polcon. De hát nem is olyan jó matekból, mint a Ricsi…

Hogy lehet csak egyszer összeépíteni a LEGO-t? Mi köze a LEGO-nak a matekhoz? Bár lehet van benne valami… ☺

Építsünk világokat

A digitális LEGO annyiból jobb a valódinál, hogy végtelen építőkockánk van. Az már más, hogy itt ezeket a kockákat magunknak kell létrehozni.

Az előző posztban említettem, hogy a Unity elsősorban 3D-s játékmotor, de van lehetőség 2D-s játékok írására is. Ez a gyakorlatban azt jelenti, hogy minden játékelem a 3-dimenziós játéktérben helyezkedik el így is, úgy is, csak a kamera “tréfál meg” bennünket.

Perspektíva vs. ortografikus vetület

A perspektíva olyan ábrázolásmód, amely a tárgyak térbeliségét ábrázolja sík felületen: esetünkben a képernyőn. A távolabbi tárgyak kisebbnek, a közelebbiek pedig nagyobbnak tűnnek. Az ortografikus vetület teljesen elhagyja a mélységet (vagyis nem veszi figyelembe a perspektivikus ábrázolás során használt z-buffert), így az azonos méretű tárgyak ugyanakkorák akkor is, ha nagyon távol vannak, és akkor is, ha nagyon közel.

Ugyanannak a három kockának perspektivikus és ortografikus megjelenítése

Ugyanannak a három kockának perspektivikus és ortografikus megjelenítése

Ha így nézzük, akkor az eredeti 1988-as játék is az ortografikus megjelenítést használja. Ezt szeretném én is elérni: csak nem majdnem-felülnézetből, hanem izometrikus nézetben.

A Soko-Ban két pályája

A Soko-Ban két pályája

Izometrikus?

A 8-bites éra bővelkedik az izometrikus megjelenítésű játékokban. Néhány példa a teljesség igénye nélkül:

Syndicate, Commandos: Behind Enemy Lines, Fallout, SimCity 2000, Baldur's Gate II: Shadows of Amn, Anno 1602, Age of Empires, Theme Hospital

Syndicate, Commandos: Behind Enemy Lines, Fallout, SimCity 2000, Baldur’s Gate II: Shadows of Amn, Anno 1602, Age of Empires, Theme Hospital

Tehát a pályát kicsit felülről (kb. 30°-kal megdöntve), és kicsit elforgatva (általában 45°-kal) szemléljük.

3D

A 3-dimenziós motor miatt kézenfekvő, hogy 3-dimenziós elemeket is alkalmazzunk. Elég létrehozni a kis kockákat és lehet is építeni. Így akár létrehozhatjuk a következő Minecraftot is. ☺

Sajnos a Unity beépített kockáit nem lehet skinezni. Viszont rendelkeznek Box Colliderrel. Az egyetlen beépített komponens, aminél meg lehet változtatni natívan, hogy mit jelenítsen meg, az a Sprite. Nem tehetünk mást, magunknak kell egy skinezhető kockát kreálnunk:

  1. Hozzunk létre egy üres GameObjectet.
    GameObject > Create Empty
  2. Nevezzük át “Cube”-nak.
    jobb klikk a GameObject-en > Rename
  3. A Cube-on belül hozzunk létre három Sprite-ot. (Mivel csak egy irányból fogjuk látni, felesleges többet renderelni.)
    GameObject > 2D Object > Sprite, majd húzzuk rá mindhárom Sprite objektumot a Cube-ra, hogy a gyerekei legyenek.
  4. Méretezzük be a Sprite-okat.
  5. Igazítsuk őket egymáshoz úgy, hogy legyen egy közös csúcsuk, illetve páronként egy közös oldaluk, és páronként a lapjaik 90°-os szöget zárjanak be.
  6. Válasszuk ki, hogy milyen képet jelenítsenek meg.
  7. Végül adjunk a Cube-hoz egy Box Collider komponenst. Ezen fog a játékos később mászkálni.

A kész félkockából csináljunk Prefabot azzal, hogy behúzzuk az Assetek közé. Innentől kezdve kódból is hívható, beállítható lesz, és lehet is építeni.

A kész félkockák

A kész félkockák

2D

Mivel annyira tetszenek a régi 8-bites játékok, így azt szereném, hogy az én játékom is pixeles, retro hatású legyen. A 3D-s objektumokkal könnyű dolgunk volt, hisz azok mindenképp passzolni fognak egymáshoz. Nem úgy a 2D-seknél – pontosabban a kvázi 2D-seknél.

Hogy könnyű legyen a pályát kezelni és a játékost irányítani, ezért a pálya elemei továbbra is kockák lesznek. A különbség az, hogy most átlátszóak, és egy Sprite-tal fogjuk őket elfedni.

Persze ez nem is olyan könnyű, mint ahogy hangzik, de pár napos próbálgatás során sikerült a megfelelő beállításokat megtalálni.

Először érdemes azt a kamerabeállítást megtalálni, amit használni fogunk a játék során. Ne felejtsük el a Projectiont Orthographicra állítani.

  1. Hozzunk létre egy kockát.
    GameObject > 3D Object > Cube
  2. Adjunk hozzá gyermek elemként egy Sprite-ot, és állítsuk be rajta a grafikánkat.
  3. Igazítsuk a Sprite-ot úgy, hogy a grafikai elem teljesen eltakarja a kockát. Vegyük figyelembe a 30°-os kameradöntést. Ekkor a sprite középpontja a kocka egyik csúcsához van közel.
  4. Töröljük a kocka Mesh Renderer és a Mesh Filter komponenseit. Ekkor csak a Box Collider marad.

Végezetül a kész pixelkockából csináljunk Prefabot.

A kész pixelkockák

A kész pixelkockák

Automate

Kézzel egymás mellé rendezgetni a kockákat elég fárasztó dolog. Szerencsére írhatunk scriptet a pálya legenerálására.

A pályát véletlenszerűen szétszórt kockákból fogjuk összerakni. A Unity beépített véletlenszámgenerátorát fogjuk használni, ezért azt a using direktívák között specifikálnunk kell.

using Random = UnityEngine.Random;

Ahhoz, hogy változókat elérjük a Unity Inspectorjában, publicnak kell lenniük.

public int columns = 5;
public int rows = 5;

A pixelkockák tárolására létrehozunk egy GameObject tömböt. Az Inspectorban ide húzzuk be a pixelkockák Prefabjait.

public GameObject[] tiles;

A pixelkockákat egy üres GameObject originjétől kezdve fogjuk tárolni: ez lesz a levelHolder.

private Transform levelHolder;

Létrehozzuk az új üres GameObjectet és eltároljuk a pozícióját. Ezek után létrehozunk a pixelkocka Prefabokból egy véletlen színű példányt és beállítjuk a Levelt szülőként. Az x és z változókat 0.32-vel be kell szorozni, mert ekkora méretűek a kockák oldalai. A kockákat az x és z tengelyen fogjuk elhelyezni, ezért az y koordináta mindig 0 lesz.

void LevelSetup()
    {
        levelHolder = new GameObject("Level").transform;

        for (int x = -1; x < columns + 1; x++)
        {
            for (int z = -1; z < rows + 1; z++)
            {
                GameObject toInstantiate = tiles[Random.Range(0,tiles.Length)];

                GameObject instance = Instantiate(toInstantiate, new Vector3(x * 0.32f, 0f, z * 0.32f), Quaternion.identity) as GameObject;

                instance.transform.SetParent(levelHolder);
            }
        }
    }

Ezután már csak végre kell hajtani a korábban definiált metódust. Erre a Unity saját beépített metódusát használjuk: az Awake-et. Ez fog lefutni, amikor a Scene betöltődik a játékban.

void Awake()
    {
        LevelSetup();
    }
}

Unityben hozzunk létre egy üres GameObjectet és húzzuk rá a scriptet. A GameObjectre kattintva a scriptnél beállíthatjuk, hogy mekkora legyen a pályánk, illetve a felhasználandó pixelkockáinkat.

Az Inspector beállításai

Az Inspector beállításai


Generált pixelkockák

Generált pixelkockák

A kódot természetesen felhasználhatjuk a félkockák generálására is:

Generált félkockák

Generált félkockák

Írjunk játszva szakdolgozatot

Amikor apukám először mutatta meg a Commodore 64-es gépén, hogy hogyan tudok egy játékot elindítani rajta, talán meg is bánta, mert ezután nem lehet kirobbantani a képernyő elől.

A Commodore 64 bekapcsolás után

A Commodore 64 bekapcsolás után

Még mindig emlékszek a kék képernyőn villogó kurzorra, ahová a következő sorokat kellett begépelnem:

LOAD"$",8
LIST

Ezután kiválasztottam annak a játéknak megfelelő sort, amivel játszani akartam és átírtam a következőre (a Commodore-on alapértelmezetten a beírt karakterek felülírták a kurzor pozícióján találtakat):

LOAD"IMPOSSIBLE MISSION",8
RUN


Az Impossible Mission játékmenete

Az Impossible Mission játékmenete

Számomra ez a játék tényleg “lehetetlen” volt, egyszer sem sikerült végigjátszanom, de nem tántorított el attól, hogy mindig újra és újra megpróbáljam. Az öreg Commodore még mindig működőképes és ugyanúgy tudok játszani rajta, mint 20 évvel ezelőtt.

A szakdolgozatom

Ennyi év elteltével sem változott a játékok iránti szeretetem, így játékfejlesztést választottam a szakdolgozatom témájának. A hangzatos cím pedig: Cross-platform játékfejlesztés Unity-ben.

Az, hogy ezzel a témával fogok foglalkozni, már jó pár éve adott volt, de a megvalósítandó játék akkor lett biztos, amikor Bonyolultságelmélet előadáson kiderült, hogy vannak kifejezetten nehéz játékok, amelyek megoldásának kiszámítása algoritmikusan belátható időn belül lehetetlen.

Ilyen játék a szókoban is.

Az 1988-ban MS-DOS-ra íródott Soko-Ban

Az 1988-ban MS-DOS-ra íródott Soko-Ban (maga a játék korábbi)

A játék célja egy labirintusban dobozokat, megadott helyre juttatni. Egyszerre csak egy dobozt lehet mozgatni, és klasszikusan csak tolni lehet őket, húzni nem. Egy pályának akkor van vége, ha az összes doboz a helyére került.

Ezt fogom megvalósítani a Unity játékmotor segítségével.

Miért Unity?

Habár több 2-dimenziós játékmotor és játékfejlesztő környezet létezik, a legfontosabb számomra, hogy a lehető legtöbb platformra el tudjam juttatni az elkészült programom.

Ezekre a platformokra lehet exportálni Unityvel:

Asztali
Windows OS X Linux
Telefon
Windows Phone 8 iOS Android
BlackBerry 10
Konzol
Xbox One Playstation 4 Wii U
Xbox 360 Playstation 3 Wii
PlayStation Vita

…és a Unity Web Playeren keresztül böngészőben is lehet játszani.

A Unity elsősorban 3-dimenziós játékok fejlesztésére lett tervezve, de kiválóan alkalmas 2D-sek készítésére is.

Néhány példa:

Hello Unity!

A játékmotor ingyenesen letölthető a fejlesztő honlapjáról. A programkód írásához használhatunk UnityScriptet, Boo-t, vagy C#-ot. Én az utóbbiban fogok fejleszteni.

A program debugolásához lehet használni a Unityba beépített MonoDevelopot, vagy a Unity VS segítségével Visual Studiot.

Miután mindent feltelepítettünk, neki is láthatunk egy új projektet készíteni: a Unityt megnyitva kiválaszthatjuk a UnityVS csomagot a fentebb említett okból, és a legördülő menüből a 2D opciót. Így a kameranézetünk alapból ortografikus lesz, a képként behúzott elemeket pedig spriteként kezeli az IDE.

A Unity Store-ból rengeteg (akár ingyenesen is) letölthető és felhasználható forrás van, a demó kedvéért egy sprite-csomagot töltöttem le. A kezelőfelületen könnyűszerrel összállíthatók a játékelemek.

Build Settings a Unityben

Build Settings a Unityben

A kész jelenet (scene) elmentése után a File > Build Settings… menüponttal jutunk el oda, hogy kiválasszuk melyik platformra szánjuk a játékunkat. A Build gomb lenyomása után elkészül a Visual Studio projekt, amelyet megnyitva kipróbálhatjuk azt. A Visual Studio Configuration Manager…-ében ne felejtsük el az architektúrát átállítani, mert alapértelmezetten ARM-ra készül a build.

Buildelés a Visual Studioban

Build a Visual Studioban


A kész "játék"

A kész "játék"