IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Miroslav Mazal:12.9.2018 13:10

Chápu to správně, že se v Unity nepoužívá konstruktor jako v C#? Mám třídu Kostka (script). Vytvořil jsem si prázdný GameObject a přídal mu script Kostka. Nazval jsem ho KostkaA. Pak jsem mu v Inspektoru určil vlastní reference, například jaké hodnoty budou mít jednotlivé strany kostky A. Pak jsem tento GameObject (KostkaA) přidal do GameManageru. A teď již jen používám v GameManageru metody KostkaA.Hod() apod. Funguje to, ale dělám to správně?

Zkusil jsem: Popsáno výše.

Chci docílit: Ujistit se, abych se nenaučil špatné postupy.

 
Odpovědět
12.9.2018 13:10
Avatar
Odpovídá na Miroslav Mazal
Luboš Běhounek Satik:12.9.2018 13:57

Konstruktor se volá při vytváření objektu, což v Unity tuším už když ho hodíš do scény, zatímco Start se volá až ve chvíli, kdy se inicialuzuje při spuštění hry. Pokud nemáš konkrétní důvod to cpát do konstruktoru, tak bych ty věci nastavoval ve Start().

Editováno 12.9.2018 13:58
Nahoru Odpovědět
12.9.2018 13:57
https://www.facebook.com/peasantsandcastles/
Avatar
Odpovídá na Luboš Běhounek Satik
Miroslav Mazal:12.9.2018 14:11

Mně to sice funguje, ale nejsem si jistý, jestli to správně chápu. A proto mám v sobě takovou nejistotu a jistý zmatek. Nejde mi jen o funkčnost, ale abych to fakt pochopil. Co jsem to teda udělal podle toho popisu nahoře? Start jsem totiž nepoužil. Vytvořil jsem script třídy Kostka, který jsem připojil k prázdnému GameObject KostkaA.
A takhle jsem ho hodil do GameManagera

public class GameManager : MonoBehaviour {

    public Kostka kostkaA;
    public Kostka kostkaB;
    public Kostka kostkaC;
    public Kostka kostkaD;
    public Kostka kostkaE;

A až pak je Start. Klidně teď můžu volat metody z KostkaA.

Funkčnost je tady https://www.youtube.com/watch?…
Stisknutím Scape vždy vyberu číslo nebo znak (jako u kostky).

 
Nahoru Odpovědět
12.9.2018 14:11
Avatar
Odpovídá na Miroslav Mazal
Luboš Běhounek Satik:12.9.2018 14:12

Poradi kodu ma smysl jen uvnitr funkci, pokud prehodis poradi funkce a treba ty kostky, na funkcnost to nema vliv, jestli narazis na tohle.

Nahoru Odpovědět
12.9.2018 14:12
https://www.facebook.com/peasantsandcastles/
Avatar
Martin Petrovaj
Tvůrce
Avatar
Odpovídá na Miroslav Mazal
Martin Petrovaj:12.9.2018 16:16

Keď si píšeš vlastný kód pre Unity a bavíme sa o tomto, potrebujeme rozlišovať dva druhy tried - tie, ktoré sú odvodené od MonoBehaviour a tie, ktoré nie sú.

MonoBehaviour-derived: nepoužívaš konštruktor vôbec, ak potrebuješ niečo nainicializovať, tak do Awake a Start. Konštruktory týchto tried sa správajú nanajvýš zvláštne a nenapadne mi z hlavy situácia, kde by sa to dalo rozumne využiť. Určite to nie je štandardné ani prehľadné.

Ostatné: tu sa už jedná o bežné C# triedy. V Unity Editore sa vo forme komponentov (ako napr. MonoBehaviour skripty, ktoré sa dajú priradiť ku gameobjectom) nevyskytujú, len ich používaš vo svojom ostatnom kóde. Keďže ide o "normálne" triedy, pri vytváraní ich inicializuješ klasicky cez konštruktor.

Aby si lepšie pochopil, čo za čiernu mágiu robí Unity s konštruktormi pri MonoBehaviours, skús si založiť prázdny projekt a trochu poexperimentovať - vypisuj do konzoly keď sa zavolá konštruktor, Start, Awake; skúšaj, čo sa dá a čo nie… Najlepšie je vždy si to vyskúšať a uvidieť sám :-)

Nahoru Odpovědět
12.9.2018 16:16
if (this.motto == "") { throw new NotImplementedException(); }
Avatar
Odpovídá na Martin Petrovaj
Miroslav Mazal:12.9.2018 16:33

Takže já jsem dělal tu první variantu? Díky přiřazení scriptu ke GameObjectu, kde se odečítá float, mohu příkazem SetActive vypnout GameObject a tím onen script, a ten pak neběží donekonečna a nezatěžuje počítač.

 
Nahoru Odpovědět
12.9.2018 16:33
Avatar
Odpovídá na Miroslav Mazal
Miroslav Mazal:12.9.2018 16:53

Mohu to tedy takto použít na ten Časovač? Ale jinak raději ne? Já ty prázdné GameObjecty se scriptem(kompo­nentem) mám v Hierarchii, a tím se asi aktivují a tak nemusí být ve Start či Awake. Je to správně?Protože mne to funguje i když ve Start ani Awake nejsou.Mám je v GameManageru nad tím.

 
Nahoru Odpovědět
12.9.2018 16:53
Avatar
Martin Petrovaj
Tvůrce
Avatar
Odpovídá na Miroslav Mazal
Martin Petrovaj:12.9.2018 16:56

Nebude to tým, že samotné kocky nijako špeciálne inicializovať nepotrebuješ (teda Kocka nepotrebuje konštruktor, Start ani Awake) a tým, že v GameManageri si tie kocky potiahol do daných polí v editore?

Pokiaľ si nejaký objekt získaš tým, že ho v editore potiahneš do public premennej napr. GameManagera, tak už ho nepotrebuješ nejako získavať v Awake / Start. Pokiaľ by si ale chcel / potreboval kocky vyhľadať a v GameManageri uložiť z kódu, pravdepodobne by si to robil v Awake / Start v GameManageri.

Nahoru Odpovědět
12.9.2018 16:56
if (this.motto == "") { throw new NotImplementedException(); }
Avatar
Miroslav Mazal:12.9.2018 17:05

Takže když to shrnu. Všechny scripty v Unity se píší odvozením z MonoBehaviour. Ale nemám používat metodu vytvoření prázdného GameObjectu a přiřazení Scriptu jako komponentu a nahrazovat tak klasický konstruktor. Je to tak?

 
Nahoru Odpovědět
12.9.2018 17:05
Avatar
Miroslav Mazal:12.9.2018 17:25

Aha ne. Buď budu používat konstruktory v MonoBehaviour a inicializovat je přes Start Awake, anebo bez MonoBehaviour klasickými konstruktory C#. Ale všechny tutoriály pro Unity jsou asi v MonoBehaviour, aspoň, co jsem zatím viděl např. šachy.

 
Nahoru Odpovědět
12.9.2018 17:25
Avatar
Martin Petrovaj
Tvůrce
Avatar
Odpovídá na Miroslav Mazal
Martin Petrovaj:12.9.2018 17:28

Skúsim radšej od začiatku:

  • GameObjecty sú objekty, entity v hre (napr. stolička, dvere, hráč, kocka, zbraň).
  • Vlastné správanie týmto GameObjectom definujeme tým, že k nim pridáme naše vlastné skripty.
  • Aby skripty vedeli jednoducho a prehľadne interagovať s enginom (a rovnako tak opačným smerom), sú odvodené od triedy MonoBehaviour. Tá nám dáva zo skriptov možnosť reagovať na udalosti enginu ako načítanie scény, vykreslenie nového snímku a pod. Ak trieda nededí z MonoBehaviour, tak ju ani nemôžeme priradiť v editore nejakému GameObjectu ako komponent.
  • Keďže MonoBehaviour skripty slúžia programátorom ako spôsob, ako interagujeme s enginom počas hry, je tomu prispôsobený ich životný cyklus vrátane inicializácie. Tá sa nevykonáva klasickým konštruktorom, ale jeho funkciu preberajú dve špeciálne metódy - Awake a Start.

To by sme mali skripty-komponenty odvodené od MonoBehaviour. Teraz ku triedam, ktoré z MonoBehaviour nededia:

  • Ak trieda nededí z MonoBehaviour, nevie sama od seba reagovať na udalosti v hre / engine, napr. na spustenie hry, vykreslenie nového snímku, nedá sa priradiť ako komponent ku GameObjectu. Nevyužívajú žiadne špeciálne metódy z Unity (napr. Update, Start, OnDestroy atď), engine nijako neovláda ich životný cyklus - je to plne v našich rukách.
  • Aby sme sprehľadnili a zjednodušili svoj kód, vedeli ho zdieľať medzi viacerými triedami a pod., často chceme opakujúce sa / univerzálne časti kódu oddeliť nielen do osobitných metód, ale aj osobitných tried. U nich ale nemá veľmi zmysel, aby samy interagovali s enginom, preto nie je žiaden dôvod, aby dedili z MonoBehaviour. Používame ich často len ako "pomocné" triedy, ale aj na ďalšie účely.
  • MonoBehaviour skripty potom tieto naše pomocné triedy využívajú tak, ako potrebujú, pričom si ich riadia samy tak, ako najlepšie vedia. Nové inštancie týchto tried vytvárajú klasicky volaním ich konštruktora keď usúdia, že to je vhodné / keď to potrebujú (napr. var generator = new GeneratorNahod­nychCisel(); ).
  • Výsledkom je prehľadnejší, kratší, efektívnejší a znovupoužiteľný kód.

A poznámka na záver:

  • Ak chceme, aby dva MonoBehaviour skripty interagovali medzi sebou, môžeme to tiež jednoducho spraviť tým, že potrebný skript získame ako akýkoľvek iný komponent z GameObjectu, na ktorom sa nachádza a ďalej s ním už pracujeme tak, ako uznáme za vhodné. Potrebný MonoBehaviour skript však takmer vždy nevytvárame, ale získavame. To znamená, že nevoláme žiaden jeho konštruktor ani špeciálne inicializačné metódy, ale predpokladáme, že už sa sám správne nainicializoval, ak to potrebuje (vo svojich metódach Awake / Start).
  • Alternatívnym riešením je aj priradenie MonoBehaviour komponentu klasicky cez editor. Hlavným mínusom tohto prístupu je ale zo zjavných dôvodov jeho neflexibilita.
Akceptované řešení
+20 Zkušeností
Řešení problému
Nahoru Odpovědět
12.9.2018 17:28
if (this.motto == "") { throw new NotImplementedException(); }
Avatar
Miroslav Mazal:12.9.2018 17:48

Super. Moc díky. Večer budu studovat.

 
Nahoru Odpovědět
12.9.2018 17:48
Avatar
Odpovídá na Martin Petrovaj
Miroslav Mazal:13.9.2018 1:16

Ahoj. První půlku jsem věděl, ale tu druhou studuji. Vytisknul jsem si všechny scripty Šachů z tutoriálu https://www.raywenderlich.com/…e-with-unity a snažím se pochopit, jak jsou propojené. Až když jsi mi to rozepsal, tak jsem si všiml, že opravdu některé scripty nejsou v přímo v MonoBehaviouru. Pochopil jsem to takto:

  1. Scripty tříd figurek (král, střelec, pěšci atd.) jsou odvozeny od třídy Piece, ale tato třída Piece je pak odvozena z MonoBehaviouru, takže tak jsou vlastně potomci MonoBahaviouru všichni (dítě a vnuci).
  2. Jejich scripty jsou pak propojeny (Inicializovány) tím, že se v GameManageru vytvoří veřejné proměnné všech figur a v Inspektoru se přetáhnou Prefaby všech figur do příslušných políček. Podle tohoto jsem to udělal s těma kostkama. A opravdu není nutné nikde je inicializovat ve Startu či Awake. Je to tak i dle Manuálu na stránkách Unity, jestli jsem to dobře přeložil. Ve Startu se už jen umístí figurky na příslušná místa ve scéně.
  3. Je tam taky třída Geometry, která není MonoBehaviour ani nic jiného. Obsahuje jen 3 statické metody. Takže, asi nepotřebuje žádné propojení a je pouze v Projektu (nenašel jsem nikde vytvoření její instance ani veřejnou proměnnou), přesto se dá na tyto metody zavolat.
  4. Také je tam třída Board, která je jako mé kostky vytvořena umístěním prázdného GameObjectu do scény, ke kterému je připojen script Board. K tomuto prázdnému GameObject Board jsou ještě připojeny dva scripty. TileSelector a MoveSelector. A protože je v GameManageru veřejná proměnná Board, a opět se prázdný GameObject Board přesunul do příslušného políčka GameManageru v Inspectoru, tak se propojily s GameManagerem všechny tři scripty.
  5. A pak je tu ještě třída Player. Také není v MonoBehaviouru, a ta jediná se asi inicializuje v Startu GameManagera
void Start ()
   {
       pieces = new GameObject[8, 8];
       movedPawns = new List<GameObject>();

       white = new Player("white", true);
       black = new Player("black", false);

       currentPlayer = white;
       otherPlayer = black;

       InitialSetup();
   }

Snad jsem to všechno pochopil. I díky tobě. Asi je to tak, že z pohledu tebe, jako zkušeného programátora v C# je možná někdy lepší jiný postup. Ale ten, který je neflexibilní, je brán jako návod na oficiálních stránkách Unity. To samé mi řekl jeden C# programátor, že Unity opustil, protože dělají věci prý nějak "divně".

Moc díky za takový pracný rozbor. Nikdy bych spoustě věcí nerozuměl, kdyby jsme to tak nerozpitvali.

 
Nahoru Odpovědět
13.9.2018 1:16
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 13 zpráv z 13.