10. Detektory vstupu a nárazu
Aby sa dala naša hra vôbec vyhrať, tak musíme vedieť zistiť, kedy loptička vošla do cieľa. Vtedy zastavíme časomieru a vypíšeme na obrazovku výsledok hry.
Na zistenie, či nejaký game objekt vošiel do nejakej oblasti využívame trigger a my už v scéne máme takýto trigger pripravený. Je to game objekt Exit a dokonca už na ňom aj je skript, ktorý pri vstúpení loptičky do triggera túto loptičku schová. My si teraz urobíme podobný skript, len namiesto schovávania loptičky ukončí hru.
Možno nie je zlý nápad pozrieť si znova lekciu, kde sme vyrábali trigger.
Vytvorte skript BallCheck a priraďte ho na game objekt Exit. Toto bude náš skript, ktorý bude zisťovať, či do exitu vbehla loptička a bude o tom informovať hlavný skript.
Popri metódach Start a Update poznajú skript v Unity viacero iných metód, ktoré sa spúšťajú automaticky. My už vieme, že Start sa spúšťa na začiatku existencie komponentu, Update sa spúšťa v každom frejme. A teraz využijeme metódu OnTriggerEnter, ktorá sa spúšťa automaticky vtedy, keď game objekt funguje ako trigger a niečo do neho vojde.
Do nášho nového skriptu BallCheck ju napíšeme takto:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallCheck : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
// Tu bude kod ktory sa vykona ked nieco vojde do triggeru
}
}
Ak začnete v editore skriptov písať OnTrigg… tak by vám mal editor už automaticky ponúknuť OnTriggerEnter a doplní za vás aj všetku bižutériu okolo (private void, other…).
Teraz do tejto metódy doplníme výpis do konzoly, aby sme si overili, či detekcia funguje:
private void OnTriggerEnter(Collider other)
{
Debug.Log("Nieco do mna voslo");
}
Teraz skúsme spustiť hru, trafiť loptičkou do exitu a sledujme konzolu:

Super, už vieme zistiť, že do triggeru niečo vošlo. Ale čo to bolo? Unity nám v tomto pomáha tak, že do premennej other, ktorá je parametrom metódy OnTriggerEnter nám uloží informácie o tom, čo to do triggeru vošlo.
Napríklad other.gameObject je odkaz na game objekt, ktorý vošiel do triggeru a takto si vypíšeme jeho meno:
private void OnTriggerEnter(Collider other)
{
Debug.Log("Nieco do mna voslo. Vola sa to: " + other.gameObject.name);
}

Úspešný koniec hry
V momente, keď do exitu vojde loptička, tak by hra mala skončiť. To znamená, že:
- Prestane bežať časomiera. Toto už vieme spraviť pomocou
Time.timeScale. - Zobrazí sa okno s informáciou o konci hry. Na toto použijeme náš panel Menu, akurát namiesto hlášky „Hra je pauznutá“ v ňom bude „Gratulujem!“
My už s časomierou aj s panelom Menu manipulujeme. Robíme to v skripte Main. Obvykle je dobré, aby sme nemali rovnakú funkcionalitu roztrúsenú po rôznych skriptoch. Namiesto toho, aby sme stopovali časomieru a zobrazovali panel Menu v skripte BallCheck bude preto lepšie, keď príkazy súvisiace s ukončením hry doplníme tiež do skriptu Main.
Akurát skript Main zase nevie o tom, kedy loptička vbehla do exitu. Prepojíme teda skript Main so skriptom BallCheck. A pri vbehnutí loptičky do exitu povieme skriptu Main, že hra skončila.
Pripojte game objekt Hra na skript BallCheck, vytvorte si na to vlastnosť s názvom hra.
Aby sme vedeli povedať skriptu Main, že hra skončila, vyrobíme v skripte Main metódu UspesnyKoniec a túto metódu zavoláme zo skriptu BallCheck.
V skripte Main to bude vyzerať takto:
public void RestartHry()
{
Debug.Log("Hra sa restartuje");
SceneManager.LoadScene(0);
}
public void UkoncenieHry()
{
Debug.Log("Zatvaram aplikaciu");
Application.Quit();
}
public void UspesnyKoniec()
{
Debug.Log("Uspesny koniec hry!");
// Tu budu dalsi prikazy ktore sa maju vykonat na konci hry
}
Keď sme chceli spúšťať akcie pri klikaní na button, vyrobili sme si v Main vlastné metódy RestartHry a UkoncenieHry. Ten istý princíp sme využili aj teraz: ak chceme spustiť nejakú akciu, keď loptička vbehne do exitu, tak sme na to vytvorili metódu UspesnyKoniec.
A túto metódu zavoláme zvnútra BallChecku, keď už vieme, že loptička vbehla do exitu:
private void OnTriggerEnter(Collider other)
{
Debug.Log("Nieco do mna voslo. Vola sa to: " + other.gameObject.name);
hra.GetComponent<Main>().UspesnyKoniec();
}
Uložiť, odskúšať, potešiť sa:

To samozrejme ešte nie je zas tak veľká radosť. Nejaký výpis do konzoly. Ale už vieme, že skript BallCheck pri zistení, že loptička vbehla do exitu zavolá metódu UspesnyKoniec v skripte Main.
A teraz čokoľvek doplníme do metódy UspesnyKoniec, tak sa vykoná pri vbehnutí loptičky do cieľa.
Doplňte to metódy UspesnyKoniec príkazy na zastavenie času a zobrazenie panelu Menu.
Upravte skript Main tak, aby sa v metóde UspesnyKoniec aj zmenil text na game objekte Hlaska na „Gratulujem!“.
Urobte, aby sa pri úspešnom konci hry vypísal aj počet úderov a čas. Radšej si zväčšite si rozmery game objektu Hlaska, aby sa do neho vošiel celý text.

Detektor nárazu
Trigger zisťuje, či do vymedzeného územia vošiel nejaký game objekt. Či loptička padla do jamky, či auto dorazilo do cieľa. V hrách ale potrebujeme vedieť aj zistiť, či sa dva game objekty zrazili.
Vyrobíme si teraz aj takýto detektor. Pri kontakte loptičky s žltým panákom otočíme smer rotácie panáka.
Vytvorte skript Enemy a priraďte ho na prefab Prekazka.
Naše prekážky nefungujú ako trigger. Nič do nich nevchádza. Majú svoju hmotu a dá sa do nich akurát tak naraziť. Preto by nám metóda OnTriggerEnter. Ak chceme niečo vykonať pri nastatí kolízie, pomôže nám metóda OnCollisionEnter:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnCollisionEnter(Collision collision)
{
Debug.Log("Au!");
}
}
Takto napísaný skript vypíše do konzoly „Au!“ vždy keď do prekážky niečo narazí:

My ale chceme, aby sa okrem „Au!“ stala aj taká vec, že sa otočí smer otáčania prekážky. Rýchlosť otáčania sa reguluje cez komponent Rotator a keď chceme zmeniť smer otáčania na opačný, stačí zmeniť znamienko rýchlosti otáčania (vlastnosť speed na komponente Rotator).
private void OnCollisionEnter(Collision collision)
{
Debug.Log("Au!");
GetComponent<Rotator>().speed = -GetComponent<Rotator>().speed;
}
Zhrnutie
Ak má game objekt na sebe nejaký druh Collider komponentu (napríklad BoxCollider) a má tento komponent nastavený ako trigger, tak vieme v skripte na tomto game objekte zistiť, či do triggeru niečo vošlo. Unity vtedy automaticky vykoná metódu OnTriggerEnter. A čo si do tejto metódy napíšeme, to sa stane.
Ak game objekt nemá collider nastavený na trigger, ale funguje ako štandardný collider, tak Unity nezavolá metódu OnTriggerEnter ale pri strete nášho game objektu s iným zavolá metódu OnCollisionEnter. A do tej si tiež môžeme napísať aké príkazy chceme.
Z jedného skriptu (napríklad náš BallCheck) vieme volať aj príkazy bežiace v inom skripte (napríklad v našom Main). Urobíme to tak, že na cieľovom skripte tieto príkazy zaobalíme do nejakej metódy a následne voláme túto metódu. Vďaka tomuto môžeme mať príbuznú funkcionalitu (napríklad v našom prípade otváranie a schovávanie menu) sústredenú v jednom skripte a z iných skriptov si to len zavoláme keď potrebujeme.
Záver
Toto je koniec tohto tutoriálu. Jeho úlohou bolo ukázať, ako sa v Unity jednotlivé game objekty nastavujú, ovládajú, ako spolu kolidujú a ako vedia medzi sebou komunikovať pomocou skriptov.
Ďalšie kroky by teraz mali smerovať k tutoriálom Model a animácia a SpaceGame.
Hotový projekt po tejto lekcii: MojaHra_10.zip
