BF Summer sales
Pouze tento týden sleva až 80 % na HTML & CSS a JavaScript
80 % bodů zdarma na online výuku díky naší Letní akci!

Lekce 8 - 3D střílečka v Unity - Střelba na nepřítele

V minulé lekci, 3D střílečka v Unity - Efekty střelby, jsme si udělali efekt střelby, zvuk výstřelu a přidali si mířidla.

V dnešní lekci budeme programovat střelbu. Když zmáčkneme levé tlačítko, tak se nám spustí animace výstřelu a zároveň se posune objekt, na který míříme, ve směru našeho výstřelu. Vše bude vypadat nějak takto:

Způsoby implementace střelby

Střelba se v Unity 3D se dá implementovat mnoha způsoby. Pojďme si představit ty nejzákladnější a vybrat pro nás ten nejlepší.

Kulka se skriptem

Jako příklad si uveďme možnost vytvořit ("spawnout") kulku po stisknutí levého tlačítka myši. Tato kulka by měla na sobě přichycený skript, který by ji okamžitě po vzniku přidával sílu ve směru, kterým je namířena. Tato možnost je složitější a komplexnější pro naši hru. Pracuje se v ní hodně s rotacemi objektu a získáváním směru.

Raycast

Druhá možnost, kterou Unity 3D nabízí a je často využívána, je udělat si polopřímku, která vychází ze zbraně a míří na místo, kam se hráč dívá:

Užívá se k tomu metoda Raycast(), kterou bychom mohli do češtiny přeložit jako "vyšli paprsek" nebo "vyšli polopřímku". Tato metoda má mnoho parametrů a nachází se ve třídě Physics. My zadáme pouze tři parametry:

  • pozice, odkud má vycházet naše polopřímka
  • směr - již jsme si řekli, že bude směřovat na místo, kam míříme. Tento směr je stejný jako směr, kterým se díváme. Nebo-li stejný směr, jaký má naše kamera. A jak získat směr, kterým "se dívá" naše kamera? Pomocí objekt.transform.forward, kdy objekt zde bude naše kamera.
  • naše proměnná, do které se budou ukládat informace o objektu, který naše polopřímka trefí. Tato proměnná je typu RaycastHit.

Nyní se můžeme vrhnout na reálné činy, když už víme jak to funguje a co potřebujeme udělat.

Příprava na programování

Nejdříve potřebujeme na něco střílet. Vytvoříme si nový objekt Cube a přichytíme na něj komponentu Rigidbody. Díky tomu ji pak můžeme přidat sílu ve směru našeho výstřelu a na objekt se budou aplikovat fyzikální zákony.

Nejdříve ze všeho klikněme pravým tlačítkem někde na volnou oblast v záložce Hiearchy, po rozrolování nabídky zvolíme možnost 3D Object a pak možnost Cube. Nově vzniklý objekt si můžete pojmenovat jakkoliv, název nebude mít žádný vliv na náš kód:

Já jsem si svou kostku pojmenoval Target. Nyní klikneme na kostku levým tlačítkem a podíváme se do záložky Inspector. Zde klikneme na tlačítko Add Component, napíšeme Rigidbody a klikneme na Rigidbody ve výsledcích vyhledávání.

Pozor, nevyberte omylem Rigidbody2D, které je určené pro 2D hry! Jinak vám pohyb nebude fungovat.

Klikneme levým tlačítkem na záložku Transform a vložíme souřadnice, např: 5, 1, 5 nebo jaké si vy sami zvolíte, aby byla kostka někde příhodně umístěna:

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

V nově přidané komponentě Rigidbody neměňte žádné hodnoty. Pokud si s tím budete chtít pohrát, tak doporučuji až po tvorbě našeho skriptu pro střelbu. Jednotlivé kolonky v této komponentě jako například Mass nebo-li hmotnost ovlivní, jaký bude mít vliv náš výstřel na tento objekt.

Poslední, co nám zbývá, je upravit vzor objektu, který budeme vytvářet vždy po výstřelu. Tento objekt nám bude tvořit efekt zásahu. Efekt je již hotový a máme ho naimportovaný spolu se všemi věcmi z našeho balíčku. Stačí kliknout levým tlačítkem myši na složku Low Poly F… v záložce Project, poté kliknout na Prefabs -> Example_P… -> Bullet_Imp… a zde dvakrát kliknout na soubor Metal Imp…, což je úder na kov.

Vedle objektu Metal Impact Prefab klikneme na šipečku a tím rozrolujeme podobjekty. Vybereme podobjekt Metal Bullet Hole Particle a deaktivujeme celý podobjekt kliknutím na čtvereček vedle názvu. To proto, že když bychom podobjekt nechali aktivní, po výstřelu by se nám objevil nehezký model "díry po výstřelu" v objektu. Nám stačí mít zde pouze aktivovaný první podobjekt, který zajišťuje jiskry a zvuk zásahu. Schválně si můžete nechat podobjekty aktivní oba a rozhodnout se, jestli se vám efekt líbí a nebo ne:

Skript EnemyHealth

Nyní našemu objektu Target přidáme ještě nový skript EnemyHealth, který bude na každém našem kdy vytvořeném nepříteli. Tento skript bude zjišťovat kolik má daný nepřítel, na kterém je náš skript, životů a pokud bude mít nulu, tak se ten daný objekt zničí.

Levým tlačítkem klikneme na objekt Target a podíváme se do záložky Inspector. Zde klikneme na tlačítko Add Component a vepíšeme název našeho skriptu EnemyHealth. Klikneme na tlačítko New Script a pak už jen na Create and Add a skript je přidán.

Skript shoot

Levým tlačítkem klikneme na náš objekt s názvem Assault_Rifle_01_FPSController. Poté v záložce Inspector klikneme na tlačítko Add Component a napíšeme shoot. Klikneme na tlačítko New Script pak už jen na Create and Add a máte hotovo:

Následně už jen dvakrát klikneme na náš skript shoot a tím ho otevřeme.

Kód

Obsah skriptu bude následující:

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

public class shoot : MonoBehaviour
{
    RaycastHit hitInfo;
    Animator objectwithAnim;
    public float dostrel;
    public float sila;
    public float poskozeni;
    public GameObject efekttrefy;
    void Start()
    {
        objectwithAnim = GameObject.FindGameObjectWithTag("Animobject").GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0)&&!objectwithAnim.GetBool("Run") && !objectwithAnim.GetBool("Holster") && !objectwithAnim.GetCurrentAnimatorStateInfo(0).IsName("Inspect")) // pokud stiskneme levé tlačítko, neběžíme, nemáme schovanou zbraň a ani není spuštěna animace prohlížení
        {
            InvokeRepeating("Shoot", 0, 0.25f); // opakuje metodu Shoot(), začíná okamžitě bez prodlevy, opakuje se každých 0.25 sekundy
        }
        if (Input.GetMouseButtonUp(0))
        {
            CancelInvoke("Shoot"); // přestává se volat metoda Shoot()
        }
    }
    void Shoot() // námi nově vytvořená metoda
    {
        if (Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hitInfo, dostrel)) // pokud něco trefíme, parametry jsou: místo, odkud půjde polopřímka, směr, kam má ukládat informace o tom, co se zasáhlo, a dálka, kam až povede.
        {
            GameObject trefa= Instantiate(efekttrefy,hitInfo.point, Quaternion.LookRotation(hitInfo.normal));
            Destroy(trefa, 1);
            if (hitInfo.transform.GetComponent<Rigidbody>()) // pokud objekt, který jsme trefili, má komponentu Rigidbody
            {
                hitInfo.transform.GetComponent<Rigidbody>().AddForce(Camera.main.transform.forward * sila); // přidáme sílu ve směru, kterým se díváme
            }
            if (hitInfo.transform.GetComponent<EnemyHealth>()) // pokud objekt, který jsme trefili, má komponentu EnemyHealth
            {
                hitInfo.transform.GetComponent<EnemyHealth>().GetDammage(poskozeni); // spouštíme metodu v jiném skriptu, parametrem jsme si nastavili množství poškození
            }
        }
    }
}

Kód je okomentovaný, projděte si jej. Opět zde máme několik věcí k podrobnějšímu vysvětlení.

RaycastHit.normal

normal je proměnná typu Vector3. Objekt, kdyby byl kolmý k tomu, co jsme pomocí neviditelné polopřímky ray trefili, by měl směr stejný jako je hodnota proměnné normal (je to tedy kolmice). Následující obrázek by vám to měl pomoci pochopit:

Tuto proměnnou má každá polopřímka ray. LookRotation() nám vrátí hodnotu ve formě Quarterion(rotace), kterou by se tím směrem daný objekt díval.

Skript EnemyHealth

Uveďme si i druhý skript:

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

public class EnemyHealth : MonoBehaviour
{
    // Start is called before the first frame update
    public float zivoty;
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
    public void GetDammage(float poskozeni) // nová metoda musí být public, abychom ji mohli zavolat z jiného skriptu
    {
        zivoty -= poskozeni; // odečte jednorázově poškození od životů
        if (zivoty <= 0)
        {
            Destroy(transform.gameObject); // metoda, která ničí herní objekty, jako parametr můžete nastavit čas od zavolání této metody, než se zničí
        }
    }
}

Inicializace public proměnných v Unity Editoru

Teď, když jsme si vytvořili kód, který nám vše řídí, nastavíme ještě hodnoty jednotlivým public proměnným. U našeho nepřítele je to hodnota životů a u našeho skriptu pro střelbu to jsou:

  • dostřel zbraně
  • síla, která působí na nepřítele
  • vzor efektu
  • poškození, které mu udělí

Proměnné skriptu shoot

Klikneme levým tlačítkem na objekt Assault_Rifle_01_FPSController. V záložce Inspector se nám zobrazí vše, co je na tomto objektu přichyceno za komponenty. Nás zajímá komponenta shoot, která je náš skript. Zde vidíme čtyři od sebe oddělená políčka s názvy: Dostrel, Sila, Poskozeni, Efekttrefy. Tato políčka představují stejnojmenné proměnné v našem skriptu. Podle toho, jaké jim nastavíte hodnoty, se hra bude chovat. Když nastavíte proměnnou Sila na 5000, tak nám objekt, na který vystřelíme a má Rigidbody, odletí ze zorného pole:

Já jsem zvolil hodnoty:

  • Dostrel: 20,
  • Sila: 100,
  • Poskozeni: 20.

Pro proměnnou Effekttrefy musíme zvolit náš dříve upravený objekt v němž máme efekty. Jako první ho najdeme opět v záložce Project. Poté ho myší přetáhneme do volného pole s nápisem None (Game Object) vedle názvu Efekttrefy. Tím se nám herní objekt přiřadí do této proměnné.

Druhý způsob je kliknout na kolečko ve volném poli s nápisem None (Game Object) a napsat do vyhledávacího okénka, které nám vyskočí: Metal Impact Prefab a poté na vyhledaný objekt kliknout levým tlačítkem.

Proměnné skriptu EnemyHealth

Klikneme levým tlačítkem na našeho nepřítele, v mém případě pojmenovaného Target. V záložce Inspector následně uvidíme náš skript, který je na našem nepříteli přichycen. Skript se jmenuje EnemyHealth. Skript by měl mít viditelnou proměnnou Zivoty. Tato proměnná, jak jste již pochopili, určuje nepřítelovo zdraví. Čím vyšší hodnota, tím více výstřelů vydrží. Já mám nastavenou hodnotu 100:

Zkouška střílení

Nyní máme vše nastaveno a můžeme spustit hru:

Zkuste si schválně měnit hodnoty u komponenty Rigidbody přichycené na našem nepříteli a sledujte, co se bude dít :)

V příští lekci, 3D střílečka v Unity - Příprava animací přebíjení zbraně, si vytvoříme přechody a parametry k jednotlivým animacím pro přebíjení.


 

Stáhnout

Staženo 7x (2.21 kB)

 

Předchozí článek
3D střílečka v Unity - Efekty střelby
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 (2)

 

 

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í!