Lekce 2 - 3D střílečka v Unity - Otáčení kamery pomocí myši

V minulé lekci, 3D střílečka v Unity - Terén a pohyb hráče, jsme si naprogramovali terén a pohyb hráče po něm.

Dnes si do našeho projektu 3D střílečky naprogramujeme otáčení kamery při pohybu myši, jak by to hráč asi z dnešních her očekával. Neděste se. Zní to složitě, ale příště už to zvládnete sami.

Tvorba skriptu pro pohyb kamery

Aby se vůbec něco s hráčem dělo, až budeme myší hýbat, musíme vytvořit skript.

Skript již tvořit umíme, dělali jsme jej pro našeho hráče, aby se mohl pohybovat. Nyní si jej vytvoříme pro kameru. Ze všeho nejdříve klikneme v okénku Hiearchy na Main Camera. Je možné, že jste si vlastní kameru pojmenovali jinak, ale to nevadí. Poté klikneme na tlačítko Add Component:

Napíšeme název skriptu pro pohyb kamery, CameraMove, a klikneme na new script. V zobrazovaném poli s názvem name se nám ukáže text, který jsme napsali, tedy CameraMove. Klikneme na tlačítko Create and Add. Tímto způsobem jsme si vytvořili skript, tentokrát na kameře. Vaše scéna by měla nyní vypadat takto:

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

Skript CameraMove

Kód bude následující, hned si jej vysvětlí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čátku máme 4 proměnné:

  • osa_x - proměnná k ukládání hodnoty myši na ose x
  • osa_y; - proměnná k ukládání hodnoty myši na ose y
  • player - Proměnná s hráčem, kterou inicializujeme později. Když dáme před naši proměnnou public, znamená to, že naše proměnná a její hodnota je vidět z Unity editoru (tam ji také potom nastavíme opravdu na hráče).
  • mousesensitivi = 12 - číslo, kterým násobíme získanou hodnotu na osách, abychom si upravili o kolik se ve výsledku posune po ose hráč nebo kamera (znáte z her jako senzitivita myši)

V metodě Update() máme řádky:

osa_x -= Input.GetAxis("Mouse Y") * mousesensitivi;
osa_y += Input.GetAxis("Mouse X") * mousesensitivi;
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Zde se nám odečítá/přičítá hodnota myši na dané ose od naší hodnoty proměnné, která je při spuštění hry nulová. Hodnotu myší získáváme pomocí metody GetAxis(), které předáme text "Mouse " a za to jakou osu chceme. Získaná data jsou jen číslo o kolik se myš po ose posunula, ne její pozice. Další hodnota by se už rovnala nule, protože už se pozice myši dál nemění a myš stojí na místě. To samé pak následuje i pro druhou osu.

Hodnotu osy X myši odečítáme, protože když chceme po ose X našeho objektu (kamery) nahoru, tak ubíráme hodnoty, můžete si to zkusit a ručně měnit hodnoty na ose X. Uvidíte, že když zadáte zápornou hodnotu osy X, tak se vám kamera otočí nahoru. Hodnotu osy X myši přičítáme, protože když chceme otočit objekt doprava po ose Y (objektu), tak se hodnoty zvětšují.

Dále:

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

Hodnoty 335 a 420 jsem určil tak, že jsem si na krátkou dobu nastavil proměnnou osa_x jako public, otáčel hráčem a díval se na hodnotu. V těchto limitech to vypadá jako reálné otáčení hlavy. Kdybychom hodnotu neomezili, mohl by hráč otáčet krkem dokola o 360° :)

Na omezení rotace používáme metodu Clamp(). Tato metoda má tři parametry:

  • vstupní hodnotu (v našem případě osa_x),
  • minimum, jaký může být výsledek metody
  • a její maximum.

Metoda nám jednoduše hodnotu ořízne, pokud se nevejde do zvolených mezí, a vrátí jako float. Pokud se vejde, jen ji vrátí.

Následuje otáčení kamery a hráče, transformovat potřebujeme oba tyto objekty:

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

Vlastnost transform nám umožňuje transformovat objekt, na kterém je skript přichycen, tedy např. otočit. Vlastnost localEulerAngles je to, co vidíme v editoru pod záložkou transform, v řádku rotation. Určujeme tedy rotaci objektu, nastavíme jakou hodnotu mají mít jednotlivé osy. Hodnotu rotace udáváme ve formátu Vector3 se třemi hodnotami, jedna hodnota pro každou osu.

Možná jste si všimli, že hodnotu pro rotaci osou Y zadáváme hráči a ne kameře. Hodnotu pro rotaci osou X zadáváme pak kameře a ne hráči. Proč? Hráč se má na rozdíl od kamery točit jen dokola. Když bychom zadali, aby se hráč otočil okolo osy X, stalo by se, že by se prakticky nadnášel, protože bychom předek kapsle posunuli víc k zemi a spodek kapsle nadzvedli. Je to vidět na následujících obrázcích:

Inicializace proměnné player

Ještě musíme udělat několik věcí, než bude vše zcela funkční. Ze všeho nejdříve musíme určit, co je naše proměnná player. Náš skript ví jen to, že je viditelná z Unity editoru a má jí měnit hodnotu rotace při pohybu myší. Skript neví, kdo nebo co je hráč. To hned napravíme.

Pokud má váš skript stejnou podobu jako můj, objeví se vám rámeček s nápisem None (Game Object) v záložce Camera Move (script). Před rámečkem bude nápis Player. Tento rámeček je naše proměnná Player:

Pro definici proměnné stačí kliknout na část rámečku s kroužkem, uprostřed něho je tečka:

Po kliknutí by se vám měl zobrazit seznam všech objektů, které máte ve vaší scéně a zároveň mohou být brány jako naše proměnná.

Vybereme objekt Capsule (pokud jste si objekt hráče nepojmenovali jinak). Díky tomu, že jsme v našem programu s názvem CameraMove přidali před proměnnou player slovo: public jsme docílili toho, že je vidět i v našem editoru a můžeme nastavit proměnné jiný objekt, než je objekt, na kterém je náš skript přichycen. Zatím jsme se tedy naučili dvě možnosti, jak definovat objekt ve skriptu:

  • pracovat přímo s objektem, na kterém je skript, např. hned přes vlastnost transform
  • definovat si pro objekt ve skriptu public proměnnou a tím si pak v editoru umožnit ji definovat

Dávejte si pozor, příliš velké množství proměnných, které jsou public neboli pro nás viditelné, mohou znatelně vytížit počítač, na kterém program běží. V příští lekci se naučíme ještě další z mnoha způsobů, jak definovat proměnnou, se kterou pracujeme.

Skript je hotov. Po spuštění hry se nám stane, že když pohneme myší, tak se naše kamera otočí a s tím i náš pohled. Možná jste si všimli, že když někam namíříte a stisknete klávesu W, hráč se pohybuje, ale ne ve směru, kam se díváte. Aby se nám hráč pohyboval ve směru pohledu, musíme upravit náš předchozí skript pro pohyb.

Úprava skriptu Move

Musíme nastavit, aby síla, která se vždy přidá při stisknutí klávesy směru chůze, např. W, působila v úhlu, kam je v daném okamžiku kamera nasměrována.

To zajistíme metodou AddRelativeForce(), která přidá sílu ve směru, kterým je objekt natočen. Tato metoda přidá sílu v aktuálním směru osy X, Y nebo Z a ne ve směru osy, která se uložila do paměti po spuštění hry. Nastavíme to následovně. Klikněte dvakrát na skript s názvem Move.cs, poté co se vám skript otevře, byste měli vidět následující:

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šude, kde máte slovo AddForce, ho nahraďte slovem AddRelativeForce. Teď můžete spustit hru. Vše by mělo fungovat, pohled ovládaný myší a pohyb ve směru kamery. Výsledek by měl vypadat následovně:

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 příští lekci, 3D střílečka v Unity - Práce s Asset Store a model zbraně, se naučíme importovat balíčky Unity Asset Store a pracovat s nimi. Do hry přidáme model zbraně.


 

Stáhnout

Staženo 16x (2.61 kB)
Aplikace je včetně zdrojových kódů v jazyce C# .NET

 

Předchozí článek
3D střílečka v Unity - Terén a pohyb hráče
Všechny články v sekci
Tvorba 3D her v Unity
Článek pro vás napsal Tomáš Brabec
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Hodně zdaru programátoři všeho druhu,doufám ,že nikdy nezažijete nudu.
Aktivity (4)

 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!