09. Interakcia s GUI
Prvky používateľského rozhrania, ktoré sme pridávali minule mali len informatívny charakter – nedalo sa na ne klikať, neboli interaktívne. Dnes si vyrobíme jednoduché menu, ktoré sa zobrazí, keď pauzneme hru. Toto menu bude mať podobu okna s tlačidlami na reštart hry a ukončenie hry.
- Vytvorte nový game objekty typu UI > Panel, pomenujte ho Menu. To bude naše okno.
- Nastavte šírku a výšku Menu na 500, 300 a ukotvite ho do stredu canvasu.
- Panel obsahuje komponent Image, cez tento komponent nastavte farbu panelu na čiernu.
Panel je obdĺžnikový kontajner, pod ktorý vieme zoskupovať ďalšie UI prvky. V našom prípade to bude textová hláška a nejaké tie tlačidlá.
- Vytvorte nový UI text, pomenujte ho Hlaska a umiestnite ho v hierarchii ako potomka game objektu Menu.
- Nastavte mu ako text nápis „Hra je pauznutá“.

Výhodou takéhoto podriadenia jedného game objektu druhému je, že všetky transformácie (pozícia, rotácia, škálovanie) sa prenášajú z nadriadeného game objektu na podriadené. A keď deaktivujeme nadriadený objekt, zmiznú s ním z obrazovky aj podriadené objekty.
Teraz vytvoríme tlačidlo na reštartovanie hry pomocou game objektu typu UI > Button a tiež ho zaradíme do Menu.
Každé UI tlačidlo v Unity pozostáva vlastne z dvoch game objektov. Nadriadený panel a podriadený text. Pomocou panelu môžeme meniť farbu tlačidla, pomocou textu jeho nápis.
- Nastavte tlačidlu zelenú farbu a nápis „Reštartovať hru“.
- Vytvorte aj červené tlačidlo s nápisom „Ukončiť hru“.

My tento panel samozrejme nechceme vidieť celú hru, len keď je pauznutá. Game objekt Menu teraz deaktivujeme a budeme ho aktivovať v skripte, v momente, keď hráč pauzne hru.
Ktorý skript nám obstaráva pauznutie hry? Toto bol skript Main, preto v ňom budeme aktivovať Menu keď bola hra pauznutá a deaktivovať Menu, keď je hra odpauznutá.
Napojte game objekt Menu na skript Main, aby sme s ním vedeli v skripte Main pracovať. Vytvorenú vlastnosť v skripte pomenujte menu.
Zatiaľ sme v skripte pri pauznutí a odpauznutí menili Time.timeScale na 0 alebo 1. A vypisovali sme do konzoly, či bola hra pauznutá alebo odpauznutá. Teraz k týmto príkazom doplníme aj aktivovanie game menu a deaktivovanie menu:
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
shots++;
Debug.Log("Pocet uderov: " + shots);
pocitadlo.GetComponent<Text>().text = shots.ToString();
}
time = time + Time.deltaTime;
cas.GetComponent<Text>().text = time.ToString();
if (Input.GetKeyDown(KeyCode.Escape))
{
if (Time.timeScale == 1)
{
Time.timeScale = 0;
Debug.Log("Pauza");
menu.SetActive(true);
}
else
{
Time.timeScale = 1;
Debug.Log("Koniec pauzy");
menu.SetActive(false);
}
}
}
Príkaz SetActive pozná každý game objekt, teda aj ten uložený vo vlastnosti menu. Podľa toho, či tomuto príkazu dáme ako parameter true alebo false, tak aktivuje alebo deaktivuje príslušný game objekt.
Uložte, vyskúšajte.
Pridanie akcie na tlačidlo a vlastná metóda
Všetko super, akurát jeden ani druhý button v menu zatiaľ nič nerobia. Lebo sme im ešte nepovedali, čo majú robiť. Od jedného tlačidla budeme chcieť, aby reštartovalo hru, od druhého aby ukončilo aplikáciu.
Button v Unity UI vie po stlačení spustiť nejakú metódu nejakého skriptu. Nevie vykonať konkrétny príkaz. Príkazy, ktoré chceme, aby sa vykonali na stlačenie tlačidla, musíme mať zapísané v nejakej metóde a túto metódu potom vie button vykonať.
My sme doteraz pracovali len s predpripravenými metódami Start a Update. Nič nám však nebráni urobiť si vlastnú metódu. Nie je to nič zložité. Pozrime si ako vyzerá zápis metódy Start v skripte Main:
void Start()
{
}
Podľa tejto šablóny si vieme v skripte Main vyrobiť aj vlastnú metódu, pomenujme ju RestartHry a prikážme jej, nech vypíše do konzoly „Hra sa restartuje“.
public void RestartHry()
{
Debug.Log("Hra sa restartuje");
// Tu bude nasledovat kod na restart hry
}
Urobili sme oproti metóde Start jednu drobnú zmenu – pridali sme slovko public. To je preto, že bez neho by nevedel iný skript alebo iný game objekt (napríklad button) zavolať našu metódu. Ak si spomínate, rovnako sme týmto slovom označovali aj verejné vlastnosti, keď sme chceli, aby boli prístupné v inšpektore alebo aby boli prístupné iným skriptom.
Keď už máme pripravenú metódu, môžeme povedať buttonu aby ju vykonal. Pozrime sa na komponent Button v zelenom tlačidle. Obsahuje sekciu On Click () a zatiaľ v tejto sekcii vykazuje, že je prázdna (List is empty):

V tejto sekcii je zoznam všetkých akcií, ktoré má button po stlačení vykonať. Môže ich byť ľubovoľne veľa. My budeme potrebovať len jednu. Poďme si ju pridať. Po stlačení + pribudne v sekcii On Click () nová akcia, zatiaľ bude prázdna:

Do prázdnej kolonky treba natiahnuť game objekt, ktorého metódu chceme volať. My chceme volať metódu skriptu Main, ktorý máme na game objekte Hra, tak tam z hierarchie pretiahneme game objekt Hra:

Následne v rozbaľovacom menu, kde teraz ešte svieti No Function vyberieme skript Main a v ňom metódu RestartHry():

Týmto sme vysvetlili buttonu, že pri clicknutí má zabrúsiť do game objektu Hra, nájsť na nom komponent Main a zavolať z neho metódu RestartHry().
Ak sme všetko urobili správne, tak po spustení hry a stlačení zeleného tlačidla sa do konzoly vypíše „Hra sa restartuje“.
Samozrejme, hra sa ešte nereštartuje, zatiaľ si to len akože vypisujeme do konzoly. Ale tento spôsob programovania – že najprv len vykonáme nejaký kontrolný výpis do konzoly – nám ukazuje, že sme pripojenie akcie na button urobili správne. Keby sme naprogramovali dve veci naraz – aj pripojenie na button aj kód na reštartovanie hry – a vo výsledku by to nefungovalo, tak by sme nevedeli, či máme zle pripojenie na button alebo kód na reštartovanie hry. Takto vieme, že jednu polovicu máme určite dobre.
Vytvorte v skripte Main metódu s názvom UkoncenieHry a nastavte nech sa vykonáva po stlačení červeného tlačidla. Do tela metódy dajte príkaz, ktorý do konzoly vypíše „Zatvaram aplikaciu“.
Reštart a ukončenie
Ostáva nám pridať kód na reštart a ukončenie. To už nesúvisí s GUI, ale bolo by fajn, keby buttony robili to, čo deklarujú.
Na zavretie aplikácie použijeme v metóde UkoncenieHry takýto kód:
public void UkoncenieHry()
{
Debug.Log("Zatvaram aplikaciu");
Application.Quit();
}
Treba povedať, že keď budeme toto testovať spúšťaním hry v editore, tak to nič neurobí. Príkaz Application.Quit() zatvára len samostatne bežiacu aplikáciu. Ak sa vám chce, môžeme si projekt zbuildovať a spustiť ako samostatnú aplikáciu. To sa riešilo v jednej z úvodných lekcií.
Ak sa vám nechce, tak na to si vypisujeme do konzoly, aby sme mali overené, že metóda UkoncenieHry sa naozaj vykonáva. A teda by sa v samostatne bežiacej aplikácii vykonal aj príkaz Application.Quit(), ktorý zavrie hru.
Na reštartovanie aplikácie použijeme jednoduchú fintu, a síce že počas behu hry nahráme nanovo scénu. Hra môže pozostávať z rôznych scén (napríklad každý level hry je jedna scéna). A počas chodu hry vieme nahrať ktorú scénu chceme. My máme v projekte zatiaľ len jednu scénu. Ale nič nám nebráni si ju nahrať znova.
Ak chceme v skripte narábať so scénami, musíme na vrch skriptu pridať balíček funkcií, ktoré narábajú so scénami: Unity.SceneManagement. Podobne ako keď sme pridávali balíček na prácu s UI:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Main : MonoBehaviour
{
public int shots = 0;
public float time = 0;
A potom už len pridáme do metódy RestartHry kód, ktorý povie Unity, že má nahrať scénu s číslom 0. To je naša scéna, lebo bola prvá.
public void RestartHry()
{
Debug.Log("Hra sa restartuje");
SceneManager.LoadScene(0);
}
Keď takto upravenú hru spustíte, tak môžete počas behu hry vyvolať menu stlačením Esc a keď si vyberiete voľbu Reštartovať hru, tak sa scéna nahrá nanovo. To znamená, že počítadlo úderov bude ukazovať 0, časomiera bude tiež na nule, obnoví sa pozícia loptičky, kamery, všetko.
Jediné, čo sa neobnoví je rýchlosť plynutia času. Po reštarte hry ostane loptička visieť vo vzduchu, žltí paňáci sa netočia ani sa nedá hýbať. Hodilo by sa nám, aby sa na začiatku hry pre istotu nastavila rýchlosť času na 1.
Preto v skripte Main doplníme do metódy Start nastavenie rýchlosti času na 1:
void Start()
{
Time.timeScale = 1;
}
Zhrnutie
Na tlačidlo v GUI vieme priradiť vykonanie nejakej akcie. Táto akcia má podobu metódy v niektorom skripte.
V našom skripte si vieme na toto vytvoriť vlastnú metódu a do nej zahrnúť príkazy, ktoré sa majú na stlačenie vykonať.
Hotový projekt po tejto lekcii: MojaHra_09.zip
