IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

2. diel - 3D strieľačka v Unity - Otáčanie kamery pomocou myši

Dnes si do nášho projektu 3D strieľačky naprogramujeme otáčanie kamery pri pohybe myši, ako by to hráč asi z dnešných hier očakával. Neľakajte sa. Znie to zložito, ale nabudúce už to zvládnete sami.

Tvorba skriptu pre pohyb kamery

Aby sa vôbec niečo s hráčom dialo, až budeme myšou hýbať, musíme vytvoriť skript.

Skript už tvoriť vieme, robili sme ho pre nášho hráča, aby sa mohol pohybovať. Teraz si ho vytvoríme pre kameru. Zo všetkého najskôr klikneme v okienku Hiearchy na Main Camera. Je možné, že ste si vlastný kameru pomenovali inak, ale to nevadí. Potom klikneme na tlačidlo Add Component:

Tvorba 3D hier v Unity

Napíšeme názov skriptu pre pohyb kamery, CameraMove, a klikneme na new script. V zobrazovanom poli s názvom name sa nám ukáže text, ktorý sme napísali, teda CameraMove. Klikneme na tlačidlo Create and Add. Týmto spôsobom sme si vytvorili skript, tentoraz na kamere. Vaša scéna by mala teraz vyzerať takto:

Tvorba 3D hier v Unity

Na obrázku je náš skript označený červeno. Dvakrát naň klikneme a upravíme jeho kód.

Skript CameraMove

Kód bude nasledujúce, hneď si ho vysvetlíme:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraMove : MonoBehaviour
{

    float osa_x;
    float osa_y;
    public GameObject player;
    float mousesensitivi = 12;

    void Start()
    {

    }


    void Update()
    {
        osa_x -= Input.GetAxis("Mouse Y") * mousesensitivi;
        osa_y += Input.GetAxis("Mouse X") * mousesensitivi;

        osa_x = Mathf.Clamp(osa_x, 335, 420);

        transform.localEulerAngles = new Vector3(osa_x, 0,0);
        player.transform.localEulerAngles = new Vector3(0, osa_y, 0);
    }
}

Na začiatku máme 4 premenné:

  • osa_x - premenná na ukladanie hodnoty myši na osi x
  • osa_y; - premenná na ukladanie hodnoty myši na osi y
  • player - Premenná s hráčom, ktorú inicializujeme neskôr. Keď dáme pred našu premennú public, znamená to, že naša premenná a jej hodnota je vidieť z Unity editora (tam ju tiež potom nastavíme naozaj na hráča).
  • mousesensitivi = 12 - číslo, ktorým násobíme získanú hodnotu na osiach, aby sme si upravili o koľko sa vo výsledku posunie po osi hráč alebo kamera (poznáte z hier ako senzitivita myši)

V metóde Update() máme riadky:

osa_x -= Input.GetAxis("Mouse Y") * mousesensitivi;
osa_y += Input.GetAxis("Mouse X") * mousesensitivi;

Tu sa nám odpočítava / pričíta hodnotu myši na danej osi od našej hodnoty premennej, ktorá je pri spustení hry nulová. Hodnotu myšou získavame pomocou metódy GetAxis(), ktoré odovzdáme text "Mouse " a za to akú os chceme. Získané dáta sú len číslo o koľko sa myš po osi posunula, nie jej pozície. Ďalšia hodnota by sa už rovnala nule, pretože už sa pozície myši ďalej nemení a myš stojí na mieste. To isté potom nasleduje aj pre druhú os.

Hodnotu osi X myši odčítame, pretože keď chceme po osi X nášho objektu (kamery) hore, tak uberáme hodnoty, môžete si to skúsiť a ručne meniť hodnoty na osi X. Uvidíte, že keď zadáte zápornú hodnotu osi X, tak sa vám kamera otočí nahor. Hodnotu osi X myši pričítame, pretože keď chceme otočiť objekt doprava po osi Y (objektu), tak sa hodnoty zväčšujú.

ďalej:

osa_x = Mathf.Clamp(osa_x, 335, 420);

Hodnoty 335 a 420 som určil tak, že som si na krátku dobu nastavil premennú osa_x ako public, otáčal hráčom a díval sa na hodnotu. V týchto limitoch to vyzerá ako reálne otáčanie hlavy. Keby sme hodnotu neobmedzili, mohol by hráč otáčať krkom dokola o 360 °:)

Na obmedzenie rotácie používame metódu Clamp(). Táto metóda má tri parametre:

  • vstupnú hodnotu (v našom prípade osa_x),
  • minimum, aký môže byť výsledok metódy
  • a jej maximum.

Metóda nám jednoducho hodnotu oreže, ak sa nezmestí do zvolených medzí, a vráti ako float. Ak sa zmestí, len ju vráti.

Nasleduje otáčanie kamery a hráča, transformovať potrebujeme oba tieto objekty:

transform.localEulerAngles = new Vector3(osa_x, 0,0);
player.transform.localEulerAngles = new Vector3(0, osa_y, 0);

Vlastnosť transform nám umožňuje transformovať objekt, na ktorom je skript prichytený, teda napr. Otočiť. Vlastnosť localEulerAngles je to, čo vidíme v editore pod záložkou transform, v riadku rotation. Určujeme teda rotáciu objektu, nastavíme akú hodnotu majú mať jednotlivé osi. Hodnotu rotácie udávame vo formáte Vector3 s tromi hodnotami, jedna hodnota pre každú os.

Možno ste si všimli, že hodnotu pre rotáciu osou Y zadávame hráči a nie kamere. Hodnotu pre rotáciu osou X zadávame potom kamere a nie hráči. Prečo? Hráč sa má na rozdiel od kamery točiť len dookola. Keď by sme zadali, aby sa hráč otočil okolo osi X, stalo by sa, že by sa prakticky nadnášal, pretože by sme predok kapsule posunuli viac k zemi a spodok kapsule nadvihli. Je to vidieť na nasledujúcich obrázkoch:

Tvorba 3D hier v Unity
Tvorba 3D hier v Unity
Tvorba 3D hier v Unity
Tvorba 3D hier v Unity

Inicializácia premenné player

Ešte musíme urobiť niekoľko vecí, než bude všetko úplne funkčné. Zo všetkého najskôr musíme určiť, čo je naša premenná player. Náš skript vie len to, že je viditeľná z Unity editora a má jej meniť hodnotu rotácie pri pohybe myšou. Skript nevie, kto alebo čo je hráč. To hneď napravíme.

Ak má váš skript rovnakú podobu ako môj, objaví sa vám rámček s nápisom None (Game Object) v záložke Camera Move (script). Pred rámčekom bude nápis Player. Tento rámček je naša premenná Player:

Tvorba 3D hier v Unity

Pre definíciu premennej stačí kliknúť na časť rámčeka s krúžkom, uprostred neho je bodka

Po kliknutí by sa vám mal zobraziť zoznam všetkých objektov, ktoré máte vo vašej scéne a zároveň môžu byť brané ako naše premenná.

Vyberieme objekt Capsule (ak ste si objekt hráčov nepomenovali inak). Vďaka tomu, že sme v našom programe s názvom CameraMove pridali pred premennú player slovo: public sme docielili toho, že je vidieť aj v našom editore a môžeme nastaviť premenné iný objekt, ako je objekt, na ktorom je náš skript prichytený. Zatiaľ sme sa teda naučili dve možnosti, ako definovať objekt v skripte:

  • pracovať priamo s objektom, na ktorom je skript, napr. hneď cez vlastnosť transform
  • definovať si pre objekt v skripte public premennú a tým si potom v editore umožniť ju definovať

Dávajte si pozor, príliš veľké množstvo premenných, ktoré sú public čiže pre nás viditeľné, môžu znateľne vyťažiť počítač, na ktorom program beží. V budúcej lekcii sa naučíme ešte ďalšie z mnohých spôsobov, ako definovať premennú, s ktorou pracujeme.

Skript je hotový. Po spustení hry sa nám stane, že keď pohneme myšou, tak sa naša kamera otočí as tým aj náš pohľad. Možno ste si všimli, že keď niekam namierite a stlačíte klávesu W, hráč sa pohybuje, ale nie v smere, kam sa pozeráte. Aby sa nám hráč pohyboval v smere pohľadu, musíme upraviť náš predchádzajúci skript pre pohyb.

Úprava skriptu Move

Musíme nastaviť, aby sila, ktorá sa vždy pridá pri stlačení klávesy smeru chôdze, napr. W, pôsobila v uhle, kam je v danom okamihu kamera nasmerovaná.

To zaistíme metódou AddRelativeForce(), ktorá pridá silu v smere, ktorým je objekt natočený. Táto metóda pridá silu v aktuálnom smere osi X, Y alebo Z a nie v smere osi, ktorá sa uložila do pamäti po spustení hry. Nastavíme to nasledovne. Kliknite dvakrát na skript s názvom Move.cs, potom čo sa vám skript otvorí, by ste mali vidieť nasledujúce:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Move : MonoBehaviour
{
    Rigidbody rb; // proměnná, která zastupuje naši komponentu Rigidbody
    void Start()
    {
        rb = transform.GetComponent<Rigidbody>(); // definujeme rb jakou má hodnotu; transform je vlastnost objektu, na který je skript napojen
        // funkce GetComponent() nám umožňuje získat komponentu jako proměnou, se kterou můžeme dále pracovat

    }

    // Update is called once per frame= tento skript se spouští každý snímek znovu a znovu pokud máte například 60fps(frames per second) skript se vám spustí 60krát za jednu sekundu.
    void Update()
    {
        if (Input.GetKey(KeyCode.D)) // využíváme podmínky, že pokud někdo stiskne klávesu W, tak se spustí tato podmínka, dokud bude klávesa zmáčknuta
        {
            rb.AddForce(new Vector3(5, 0, 0)); // Zde využíváme toho, že na proměnou přešly vlastnosti a metody komponenty RIGIDBODY.
            // Metoda AddForce() přidá sílu do určitého směru, který nastavujeme pomocí os x, y a z. Zde přidáme hodnotu síly 5 na osu x (do strany).
        }
        if (Input.GetKey(KeyCode.A))
        {
            rb.AddForce(new Vector3(-5, 0, 0));
            // Zde přidáme hodnotu síly -5 na osu x (do strany).
        }
        if (Input.GetKey(KeyCode.W))
        {
            rb.AddForce(new Vector3(0, 0, 5));
            // Zde přidáme hodnotu síly 5 na osu z (dopředu).
        }
        if (Input.GetKey(KeyCode.S))
        {
            rb.AddForce(new Vector3(0, 0, -5));
            // Zde přidáme hodnotu síly -5 na osu z (dozadu).
        }
    }
}

Všade, kde máte slovo AddForce, ho nahraďte slovom AddRelativeForce. Teraz môžete spustiť hru. Všetko by malo fungovať, pohľad ovládaný myšou a pohyb v smere kamery. Výsledok by mal vyzerať nasledovne:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Move : MonoBehaviour
{
    Rigidbody rb; // proměnná, která zastupuje naši komponentu Rigidbody
    void Start()
    {
        rb = transform.GetComponent<Rigidbody>(); // definujeme rb jakou má hodnotu; transform je vlastnost objektu, na který je skript napojen
        // funkce GetComponent() nám umožňuje získat komponentu jako proměnou, se kterou můžeme dále pracovat

    }

    // Update is called once per frame= tento skript se spouští každý snímek znovu a znovu pokud máte například 60fps(frames per second) skript se vám spustí 60krát za jednu sekundu.
    void Update()
    {
        if (Input.GetKey(KeyCode.D)) // využíváme podmínky, že pokud někdo stiskne klávesu W, tak se spustí tato podmínka, dokud bude klávesa zmáčknuta
        {
            rb.AddRelativeForce(new Vector3(5, 0, 0)); // Zde využíváme toho, že na proměnou přešly vlastnosti a metody komponenty RIGIDBODY.
            // Metoda AddForce() přidá sílu do určitého směru, který nastavujeme pomocí os x, y a z. Zde přidáme hodnotu síly 5 na osu x (do strany).
        }
        if (Input.GetKey(KeyCode.A))
        {
            rb.AddRelativeForce(new Vector3(-5, 0, 0));
            // Zde přidáme hodnotu síly -5 na osu x (do strany).
        }
        if (Input.GetKey(KeyCode.W))
        {
            rb.AddRelativeForce(new Vector3(0, 0, 5));
            // Zde přidáme hodnotu síly 5 na osu z (dopředu).
        }
        if (Input.GetKey(KeyCode.S))
        {
            rb.AddRelativeForce(new Vector3(0, 0, -5));
            // Zde přidáme hodnotu síly -5 na osu z (dozadu).
        }
    }
}

V budúcej lekcii, 3D strieľačka v Unity - Práca s Asset Store a model zbrane , sa naučíme importovať balíčky Unity Asset Store a pracovať s nimi. Do hry pridáme model zbrane.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 136x (2.49 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
3D strieľačka v Unity - Terén a pohyb hráča
Všetky články v sekcii
Tvorba 3D hier v Unity
Preskočiť článok
(neodporúčame)
3D strieľačka v Unity - Práca s Asset Store a model zbrane
Článok pre vás napísal Tomáš Brabec
Avatar
Užívateľské hodnotenie:
2 hlasov
Hodně zdaru programátoři všeho druhu,doufám ,že nikdy nezažijete nudu.
Aktivity