02. Náhodný nepriateľ
V tejto lekcii pridáme pohyb na lietajúci tanier. Budeme generovať náhodné pozície a tanier sa na ne bude sám presúvať. Nie je to veľmi inteligentný pohyb, ale nikto nepovedal, že mimozemský život musí byť inteligentný.
Otvorte svoj projekt alebo si stiahnite hotový: SpaceGame_01.zip
Vytvorte nový skript UfoController a priraďte ho na game objekt UFO.
Vytvorte v triede UfoController
vlastnosť speed
na regulovanie rýchlosti pohybu (podobne ako pri astronautke)
Náhodný cieľ
Aby tanier mal nejaký cieľ, za ktorým sa bude hýbať, musíme mu nejaký vytvoriť. Cieľ je nejaké miesto v priestore a na miesta v priestore máme v Unity vektory. Vytvoríme preto novú vlastnosť target
, bude typu Vector3
. A bude privátna, lebo ju nepotrebujeme nastavovať v editore ani k nej pristupovať z iných skriptov:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UfoController : MonoBehaviour { public float speed = 1; private Vector3 target; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } }
Prečo sme vlastnosť target
vytvorili ako Vector3
, keď potrebujeme len Vector2
? Zatiaľ to neriešme, vrátime sa k tomu o pár odstavcov nižšie.
Pri štarte hry vygenerujeme náhodnú pozíciu v priestore. Na náhodné čísla (ale napríklad aj náhodné farby) existuje v Unity pomocná trieda Random
. Tá má veľa užitočných metód a my použijeme metódu Range, ktorá vygeneruje náhodné číslo so zadaného intervalu.
V scéne si vyskúšajme, že aké minimálne a maximálne X,Y pre UFO sú prijateľné. Tu to vychádza na -7.5 až +7.5 pre X a -4 až +4 pre Y.

Už vieme z akého rozsahu chceme X, vieme z akého rozsahu chceme Y. Poďme vytvoriť nový vektor.
Vytvárame nový vektor
Zatiaľ sme používali vektory v podobe Vector2.left
, Vector2.top
a podobne. To sú preddefinované vektory, my ale teraz chceme svoj vlastný vektor. Nový vektor (a aj iné nové objekty iných tried v jazyku C#) sa vytvára pomocou slova new
. Takto:
void Start() { target = new Vector3(0, 0, 0); }
Tento príkaz vytvorí nový vektor a nastaví mu x na 0, y na 0 a z na 0. Samozrejme, toto ešte nie je náš želaný cieľ. My chceme, aby náš cieľ bol náhodný z rozsahu -7.5 až +7.5 pre X a -4 až +4 pre Y. Takže takto:
void Start() { target = new Vector2(Random.Range(-7.5f, 7.5f), Random.Range(-4, 4), 0); }
Tým by sme mali vytvorený náhodný cieľ, ktorý sa vygeneruje na začiatku hry a bude ležať v rámci obrazovky. Poďme naučiť UFO presunúť sa do tohto cieľa
Vektorový počet pre začiatočníkov
Spomeňme si, akým spôsobom sme hýbali astronautku:
// Ak je stlacena sipka doprava if (Input.GetKey(KeyCode.RightArrow)) { // Pohni sa kusok smerom doprava transform.Translate(Vector2.right * speed * Time.deltaTime); }
Astronautku sme hýbali v smere vektora Vector.right
a násobíme tento posun rýchlosťou a časom.
UFO budeme tiež chcieť podobne, akurát vektor posunu, v ktorom smere budeme UFO hýbať, nebude Vector2.right
. Čo bude teda vektor posunu?
V minulej lekcii sme si ukázali, že:
Stará pozícia + posun = nová pozícia
To sa dá prehodiť aj takto:
Posun = nová pozícia – stará pozícia.
Stará pozícia je miesto, kde je UFO teraz (čiže transform.position
) Nová pozícia je cieľ, kam chceme UFO presunúť, čiže target
.
Poďme teda do triedy UfoController
dopísať príkazy na posun smerom do cieľa. Budeme ich písať do Update()
, lebo je to pohyb a ten sa má diať v každom frejme.
Najprv si vypočítame vektor posunu. Na tento účel si vytvoríme novú premennú direction
. A do nej uložíme „nová pozícia mínus stará pozícia“:
void Update() { Vector3 direction = target - transform.position; }

Tu sa vrátim k tomu, prečo sme target
zadefinovali ako Vector3
a nie Vector2
. Komponent transform
uchováva pozíciu ako Vector3
aj keď sme v 2D projekte. Takže transform.position
je typu Vector3
. A keby bol target
typu Vector2
, tak pre počítač sú to dva rôzne dátové typy a nevie ako ich skombinovať. Vyvstáva potom otázka, že načo vôbec používať Vector2
, keď Vector3
vie to isté aj viac. Pre jednoduchosť, ak je to možné. V tomto momente to možné nie je, tak používame Vector3
.
V premennej direction
teraz máme uložený smer posunu z terajšej pozície k cieľu. Je to smer posunu podobne ako sme pri astronautke použili smer posunu Vector2.right
. Takže podobne ako pri astronautke aj tu použijeme metódu transform.Translate()
:
void Update() { Vector3 direction = target - transform.position; transform.Translate(direction * speed * Time.deltaTime); }
Keď teraz spustíme hru, UFO sa samo premiestni na náhodnú pozíciu:
Jeden problém ostáva, a síce, že UFO sa nehýbe rovnako rýchlo. Začne rýchlo a postupne – ako sa blíži k cieľu – spomaľuje. Prečo to?

Keď pohyb začína, šípka direction
od aktuálnej pozície do novej je dlhá dlhočizná. Takúto šípku keď vynásobíme krát rýchlosť krát čas, dostaneme dlhý úsek. V prvom frejme teda posunieme UFO o dlhý úsek. V ďalšom frejme už rozdiel medzi aktuálnou pozíciou a cieľom bude o trochu kratšia šípka. Preto v ďalšom frejme sa UFO posunie o menší úsek. A tak ďalej a tak ďalej. A ku koncu, kedy rozdiel medzi aktuálnou pozíciou a cieľom je už len kratučká šípka, tak sa UFO hýbe pomaličky.
My chceme, aby sa UFO hýbalo konštantou rýchlosťou. Mimozemšťania predsa nespomaľujú, otáčajú sa na mieste a smer pohybu menia bez brzdenia. To vie každý.

Vektorový počet pre pokročilých
Aby sme napravili pribrzdené správanie nášho UFA, potrebujeme zachovať jednotnú dĺžku šípky počas celej cesty. Keby tak bola nejaká funkcia, ktorá vie konkrétny vektor dať na nejakú jednotnú dĺžku, napríklad 1.
A ona aj je, volá sa Normalize()
:
void Update() { // Vypocitaj posun od aktualnej pozicie do ciela Vector3 direction = target - transform.position; // Znormalizuj tento posun direction.Normalize(); // A posun sa o posun krat rychlost krat cas transform.Translate(direction * speed * Time.deltaTime); }
Príkaz direction.Normalize()
znormalizuje vektor direction
. Normalizácia znamená, že smer šípky sa zachová, ale jej dĺžka sa skráti (resp. predĺži) tak aby bola dlhá presne 1. V každom frejme je takto znormalizovaná šípka rovnako dlhá, a tak sa UFO posúva o rovnaký úsek a nespomaľuje.
Zhrnutie
- Pozície objektov sa uchovávajú vo vlastnostiach a v premenných typu vektor. (
Vector2
aleboVector3
, podľa potreby) - Takisto sa uchovávajú aj smery posunu.
- Aktuálna pozícia + vektor posunu = nová pozícia
- A naopak: Vektor posunu = cieľová pozícia – aktuálna pozícia.
- Rôzne dlhé šípky vieme znormalizovať na jednotnú dĺžku a ich smer sa zachová.
- Vo vesmíre vás nikto nepočuje kričať.
Tu je na stiahnutie hotový projekt: SpaceGame_02.zip