Lekce 5 - Unity (C#) Android: Generování stalagů, 2. část
V minulé lekci, Unity (C#) Android: Generování stalagů, jsme si vytvořili kolem mapy pohyblivý tunel, čímž jsme ji ohraničili, a vygenerovali si 50 stalagů.
Mapa má však stále ještě rezervy a proto budeme v generování pokračovat i v dnešním Unity 3D Android tutoriálu.
Různá výška překážek
Aby všechny překážky nebyly stejně velké, upravíme si metodu
GenerateStalag()
v našem StartScript
do
následující podoby:
void GenerateStalag(Vector2 p) { GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject; Vector3 scale = g.transform.localScale; scale.y = Random.Range(0.5f, 1.2f); g.transform.localScale = scale; }
Za vysvětlení stojí řádek:
GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject;
Kód funguje stejně jako předtím, jen s menším rozdílem. Náš vytvořený objekt se nám uloží do proměnné. S touto proměnnou následně můžeme pracovat a upravit libovolné vlastnosti nového objektu.
Vytvoříme si plně vybarvené okraje naší obrazovky, abychom tam neměli
takovou díru. Výplň si přesuneme do objektu Borders1
a
uložíme. Dotyčnou výplň vytvoříme s pomocí modrého obdélníku, který
je ke stažení v minulé lekci. Stačí sprite přesunout na scénu a
roztáhnout do požadované velikosti:

V Prefabu našeho stalagu si změníme Order in Layer na -1
a
potvrdíme. To zajistí, aby se nám nepřekrýval s jinými sprity:

Aby naše hra byla lépe optimalizovaná, Prefabu našeho krápníku
vytvoříme vlastní vrstvu. Pojmenujeme si ji StalagLayer
a to
samé uděláme s Prefabem zdi, které vytvoříme vrstvu
BorderLayer
:

Dále v Edit -> Project settings -> Physics2D nastavíme, aby spolu
StalagLayer
a BorderLayer
nekolidovaly. To děláme
proto, že na obou objektech máme collider a kdyby spolu tyto objekty neustále
kolidovaly, mohla by se tím razantně zvýšit náročnost naší hry, která
by se mohla následně sekat:

Stalagy ze země
Zatím nám překážka visí pouze ze stropu, zařídíme, aby trčela i ze
země. To provedeme další změnou skriptu StartScript
:
void Start() { for (int i = 0; i < count; i++) { Vector2 pos = new Vector2(); pos.x = offset + i * distance; int r = Random.Range(0, 2); int rotateIndicator = 1; if (r == 0) { pos.y = 4.5f; // může se lišit podle toho. jak máte vzdálený strop a podlahu od sebe } else { pos.y = -4.5f; // může lišit podle toho, jak máte vzdálený strop a podlahu od sebe rotateIndicator = -1; } GenerateStalag(pos, rotateIndicator); } } void GenerateStalag(Vector2 p, int rotateInd) { GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject; Vector3 scale = g.transform.localScale; scale.y = Random.Range(0.5f, 1.2f) *rotateInd; g.transform.localScale = scale; }
Když hru spustíme, můžeme vidět, že se nám stalagy náhodně otočily.
Optimalizace
Dále si hru trochu optimalizujeme. Teď generujeme všechny stalagy najednou, jenže to může být docela zbytečné. Tudíž jich budeme vždy generovat jen pár.
Na náš StartingObject
si přidáme Box collider a odškrtneme,
že se jedná o trigger. Zvětšíme a posuneme ho tak, aby byl na výšku přes
celou naší hrací plochu a zároveň byl alespoň trochu široký. Následně
ho přesuneme před hráče:

Dále hráči přidáme tag Player
, který je v Unity již
předvytvořený:

Tagy se objektům většinou přiřazují kvůli identifikaci.
Není praktické rozeznávat objekty pomocí jména. Představte si situaci, kdy
generujete hordy nepřátel, každý nepřítel s jiným jménem a máte jich
stovky a chcete zjistit, jestli nějaký nepřítel například neudeřil
hráče. Museli bychom zkontroloval všechna možná jména. Jednodušší
způsob je všem nepřátelům přiřadit tag Enemy
a jen
zjišťovat, zda objekt s tagem Enemy
udeřil hráče.
Dále si upravíme náš skript:
public GameObject stalagPrefab; public float distance = 10; public float offset = 10; public int count = 50; public Vector3 lastPos; void Start() { lastPos = transform.position; //GenerateSet(); // již nepotřebujeme ve startu } void GenerateSet() { for (int i = 0; i < count; i++) { Vector2 pos = new Vector2(); pos.x = lastPos.x + (2*distance) + offset + i * distance; int r = Random.Range(0, 2); int rotateIndicator = 1; if (r == 0) { pos.y = 4.5f; // toto číslo se může lišit podle toho, jak máte vzdálený strop a podlahu od sebe } else { pos.y = -4.5f; // toto číslo se může lišit podle toho, jak máte vzdálený strop a podlahu od sebe rotateIndicator = -1; } GenerateStalag(pos, rotateIndicator); } } void GenerateStalag(Vector2 p, int rotateInd) { GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject; Vector3 scale = g.transform.localScale; scale.y = Random.Range(0.5f, 1.2f) *rotateInd; g.transform.localScale = scale; } // vždy, když hráč proletí colliderem StartingObject, vygenerují se nové překážky a následně se náš celý objekt posune void OnTriggerEnter2D(Collider2D col) { if (col.CompareTag("Player")) { GenerateSet(); lastPos = transform.position; lastPos.x += count * distance; transform.position = lastPos; } }
Dále zajistíme, aby se naše překážky generovaly na správných místech. Stačí pouze lehce upravit naší metodu na generování:
void GenerateStalag(Vector2 p, int rotateInd) { GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject; Vector3 scale = g.transform.localScale; scale.y = Random.Range(0.5f, 1.2f) *rotateInd; g.transform.localScale = scale; Bounds bound = g.GetComponent<SpriteRenderer>().bounds; p.y -= bound.size.y / 2 * rotateInd; g.transform.position = p; }
Bounds jsou hranice (velikost) objektu. Vzali jsme si tedy velikost našeho spritu na stalagmit a vypočítali jsme díky tomu jejich umístění.
Když hru spustíme, můžeme vidět, že už vypadá pěkně.
Náhodná šířka a více druhů stalagů
Hráče může omrzet, když uvidí pouze jednu a tu samou překážku stále dokola, jen jinak velkou. Přidáme tedy i náhodnou šířku stalagů a dále i více druhů.
Více druhů stalagů
Abychom generovali více druhů stalagů, potřebujeme si vytvořit pole našich překážek:
public GameObject[] stalagPrefab;
Z naší proměnné pro Prefab vytvoříme pole. A následně musíme upravit ještě část kódu na generování:
GameObject g = Instantiate(stalagPrefab[Random.Range(0, stalagPrefab.Length)], p, Quaternion.identity) as GameObject;
Random.Range(0, stalagPrefab.Length)
nám zajistí
vygenerování stalagmitu na náhodném indexu z celé délky pole našich
stalagmitů.
Teď, když se podíváme do Inspectoru na náš StartingObject
,
můžeme tam vidět možnost zvolit velikost našeho pole. My zvolíme
4
:

Můžete použít sprity, které jsem vám dal ke stažení a nebo si můžete vytvořit vlastní:

Následně uděláme to samé jako s prvním stalagem. Nastavíme barvu,
collider, order in layer, Layer a uložíme jako Prefab. Následně tento Prefab
přetáhneme v Inspectoru do pole Stalag Prefab
:

Když hru spustíme, můžeme vidět, že se generují různé druhy.
Takto si můžeme vytvořit libovolný počet různých stalagů. Pokud nám budou připadat velké a nebo malé, můžeme si velikost generování libovolně upravit.
Pro lepší přehlednost si vytvoříme další proměnné:
public float minHeight; public float maxHeight; public float minWidth; public float maxWidth;
Ve finále si upravíme naší metodu na generování, aby se náhodně určovala i šířka stalagů:
scale.y = Random.Range(minHeight, maxHeight) *rotateInd; scale.x = Random.Range(minWidth, maxWidth);
Od teď můžeme pohodlně z Inspectoru měnit naše hodnoty a nemusíme pracně hledat v kódu. Hodnoty nastavíme následně:

Pokud se nám někdy bude zdát, že hodnoty potřebují upravit, uděláme to z tohoto místa.
Závěr
Pro dnešek to bude vše. Doufám, že se vám série tutoriálů líbí a naučili jste se něco nového. Pokud máte nějaké připomínky či nápady, zanechte komentář, rád se inspiruji.
Příště se v lekci Unity (C#) Android: GUI - Menu 1 podíváme na vytvoření menu.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkamiStaženo 466x (92.84 kB)