NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

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

V minulé lekci, 3D střílečka v Unity - Ovládání animací, jsme si upravili skript Move.cs tak, aby ovládal naše animace.

V dnešním Unity 3D tutoriálu budeme programovat střelbu. Při stisku levého tlačítka spustíme animaci výstřelu a zároveň necháme posunout zasažený objekt:

Tvorba 3D her v Unity

Způsoby implementace střelby

Střelba se v Unity 3D může implementovat mnoha způsoby. Představíme si dva základní a jeden si vybereme.

Kulka se skriptem

První možností je 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 přidával sílu ve směru výstřelu. Tato možnost je složitější. Pracuje se v ní hodně s rotacemi objektu a získáváním směru.

Raycast

My si vybereme druhou možnost, spočívající v polopřímce vycházející ze zbraně a mířící na místo, kam se hráč dívá:

Tvorba 3D her v Unity Pro tuto možnost se používá metoda Raycast() ze třídy Physics. Z možných parametrů metody využijeme pouze tři:

  • pozice - odkud má vycházet naše polopřímka,
  • naše proměnná typu RaycastHit, do které se budou ukládat informace o objektu, který naše polopřímka trefí,
  • směr - 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.

Směr, kterým "se dívá" naše kamera, získáme z objekt.transform.forward, kde objekt bude naše kamera.

Příprava na programování

Nejdříve potřebujeme mít na něco střílet. Vytvoříme si nový objekt kostky Cube a přichytíme na něho komponentu Rigidbody. Díky tomu pak kostce můžeme přidat sílu ve směru našeho výstřelu a budou se na ni 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 otevření nabídky zvolíme možnost 3D Object => Cube:

Tvorba 3D her v Unity

Nově vzniklý objekt si pojmenujeme například 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

Klikneme levým tlačítkem na záložku Transform a vložíme souřadnice, např: 5, 1, 5:

Tvorba 3D her v Unity

V nově přidané komponentě Rigidbody neměňme žádné hodnoty. Jednotlivé kolonky v této komponentě, jako například Mass (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é přejdeme na Prefabs/Example_P…/Bullet_Imp…/ a zde dvakrát klikneme na soubor Metal Imp…, což je úder na kov.

Vedle objektu Metal Impact Prefab klikneme na šipečku, aby se nám zobrazily 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 v objektu nehezký model "díry po výstřelu". Nám stačí mít zde pouze aktivovaný první podobjekt, který zajišťuje jiskry a zvuk zásahu.

Tvorba 3D her v Unity

Je možné si nechat aktívní oba podobjekty a případně deaktivovat objekt Metal Bullet Hole Particle až později.

Skript Shoot

Nejprve si vytvoříme nový skript a poté ho začneme upravovat.

Vytvoření skriptu Shoot

Levým tlačítkem klikneme na náš objekt s názvem Assault_Rifle01_FPSCon­troller. Poté v záložce Inspector klikneme na tlačítko Add Component a napíšeme Shoot. Klikneme na tlačítko New Script => Create and Add:

Tvorba 3D her v Unity

Úprava skriptu Shoot

Na náš skript Shoot dvakrát klikneme a tím ho otevřeme. Upravíme ho tak, aby se při stisknutí levého tlačítka myši provedl výstřel.

Proměnné

Na začátek třídy Shoot přidáme tyto proměnné:

  • hitInfo - pro ukládání informací o "paprsku",
  • objectwithAnim - pro instanci typu Animator,
  • dostrel - pro dostřel zbraně,
  • poskozeni - pro poškození zasaženého nepřítele,
  • sila - pro sílu působící na nepřítele,
  • efekttrefy - pro efekt zasažení.

Kód je následující:

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

public class Shoot : MonoBehaviour
{
    RaycastHit hitInfo;
    Animator objectwithAnim;
    public float dostrel;
    public float sila;
    public float poskozeni;
    public GameObject efekttrefy;

    ...
}

Metoda Start()

Dále v metodě Start() nastavíme instanci proměnné objectwithAnim:

void Start()
{
    objectwithAnim = GameObject.FindGameObjectWithTag("Animobject").GetComponent<Animator>();
}

Metoda Update()

Do metody Update() přidáme dvě podmínky:

void Update()
{
    if (Input.GetMouseButtonDown(0) && !objectwithAnim.GetBool("Run") && !objectwithAnim.GetBool("Holster") && !objectwithAnim.GetCurrentAnimatorStateInfo(0).IsName("Inspect"))
    {
        InvokeRepeating("ShootBullet", 0, 0.25f);
    }

    if (Input.GetMouseButtonUp(0))
    {
        CancelInvoke("ShootBullet");
    }
}

V první podmínce hlídáme stisknutí levého tlačítka myši, běh, schování zbraně a spuštění animace prohlížení. Pokud bude podmínka splněna, zavoláme metodu InvokeRepeating() s parametry:

  • ShootBullet - název metody, která se má zavolat (za okamžik si ji napíšeme),
  • 0 - okamžité zavolání metody ShootBullet() s nulovou prodlevou,
  • 0.25f - opakované volání metody ShootBullet() každých 0.25 sekund.

Pokud je v druhé podmínce levé tlačítko myši vyhodnoceno jako uvolněné, v těle podmínky zrušíme opakované volání metody ShootBullet().

Pro metody InvokeRepeating() a CancelInvoke() se jako první parametr zadává název metody bez závorek.

Metoda ShootBullet()

Nakonec si do skriptu Shoot napíšeme novou metodu ShootBullet(). Metoda bude kontrolovat, jestli jsme něco zasáhli. Pokud ano, tak se na konci vytvoří efekt a udělí zasaženému nepříteli poškození:

void ShootBullet()
{
    if (Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hitInfo, dostrel))
    {
        GameObject trefa = Instantiate(efekttrefy,hitInfo.point, Quaternion.LookRotation(hitInfo.normal));
        Destroy(trefa, 1);

        if (hitInfo.transform.GetComponent<Rigidbody>())
        {
            hitInfo.transform.GetComponent<Rigidbody>().AddForce(Camera.main.transform.forward * sila);
        }

        if (hitInfo.transform.GetComponent<EnemyHealth>())
        {
            hitInfo.transform.GetComponent<EnemyHealth>().TakeDamage(poskozeni);
        }
    }
}
První podmínka

V první podmínce hlídáme zasažení objektu. Voláme metodu Physics.Raycast() s návratovou hodnotou typu RaycastHit, které předáme tyto parametry:

  • Camera.main.transform.position - místo, odkud půjde polopřímka,
  • Camera.main.transform.forward - směr, jakým má jít polopřímka,
  • out hitInfo - kam se má ukládat informace o zasažení,
  • dostrel - vzdálenost, kam až povede polopřímka.

V těle podmínky si nejprve necháme vrátit objekt typu GameObject z metody Instantiate(), které předáme:

  • efekt zasažení efekttrefy,
  • definované pozice hitInfo.point,
  • rotaci Quaternion.LookRotation(hitInfo.normal).

Hodnotou normal typu Vector3 u rotace definujeme, že se nám má vrátit směr kolmý k zasaženému objektu:

Tvorba 3D her v Unity

Poté v těle podmínky zavoláme metodu Destroy() s parametry:

  • trefa - objekt ke zničení,
  • 1 - doba v sekundách, za kterou se má objekt zničit.
Druhá podmínka

Druhou podmínku napíšeme do těla první podmínky za volání metody Destroy(trefa, 1). V podmínce zjišťujeme, zda zasažený objekt má komponentu typu Rigidbody. Pokud ano, tak přidáme sílu objektu ve směru, kterým se díváme.

Třetí podmínka

Také třetí podmínku si napíšeme do těla první podmínky a to za tělo druhé podmínky. V podmínce zjišťujeme, zda zasažený objekt má skript EnemyHealth. Pokud ano, tak objektu udělíme poškození pomocí metody TakeDamage().

Metodu TakeDamage() si definujeme v dalších lekcích.

Skript EnemyHealth

Nyní našemu objektu Target přidáme ještě nový skript EnemyHealth. Ve skriptu zjistíme, kolik životů má nepřítel, na kterém je náš skript. Pokud nebude mít žádný život, tak objekt nepřítele zničíme 😀

Vytvoření skriptu EnemyHealth

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 napíšeme název našeho skriptu EnemyHealth. Klikneme na tlačítko New Script => Create and Add a skript je přidán.

Úprava skriptu EnemyHealth

Ve skriptu nebudeme vůbec používat metodu Start() a Update(), které odstraníme. Do skriptu si přidáme proměnnou health:

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

public class EnemyHealth : MonoBehaviour
{
    public float health;
}

Metoda TakeDamage()

Nejprve z životů odečteme poškození damage. V podmínce otestujeme, zda health<= 0 a případně zničíme objekt nepřítele transform.gameObject metodou Destroy():

public void TakeDamage(float damage)
{
    health -= damage;

    if (health <= 0)
    {
        Destroy(transform.gameObject);
    }
}

Metodu budeme chtít volat z jiných skriptů, proto jsme ji nastavili modifikátor přístupu public.

Inicializace public proměnných v Unity Editoru

Proměnným obou skriptů nastavíme hodnoty.

Proměnné skriptu Shoot

Klikneme levým tlačítkem na objekt Assault_Rifle01_FPSCon­troller. V záložce Inspector se nám zobrazí komponenty přiřazené objektu Assault_Rifle01_FPSCon­troller. Vybereme komponentu Shoot, která představuje náš skript Shoot:

Tvorba 3D her v Unity

V komponentě Shoot vidíme čtyři políčka se shodnými názvy proměnných našeho skriptu. Nastavíme jim například tyto hodnoty:

  • pro Dostrel hodnotu 20,
  • pro Sila hodnotu 100,
  • pro Poskozeni hodnotu 20.

V políčku Effekttrefy musíme zvolit náš dříve upravený objekt, v němž máme efekty. 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é.

Alternativně klikneme na kolečko ve volném poli s nápisem None (Game Object) a napíšeme do vyhledávacího okénka : Metal Impact Prefab. Poté na vyhledaný objekt klikneme levým tlačítkem.

Proměnné skriptu EnemyHealth

Klikneme levým tlačítkem na našeho nepřítele, který jsme si nazvali Target. V záložce Inspector se přesuneme do oddílu Enemy Health (Script). Do políčka Health vložíme hodnotu 100:

Tvorba 3D her v Unity

Políčko Health reprezentuje naši proměnou health. Čím vyšší ji dáme hodnotu, tím více výstřelů nepřítel vydrží.

Zkouška střílení

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

Tvorba 3D her v Unity

Zkusme si měnit hodnoty u komponenty Rigidbody přichycené na našem nepříteli a sledovat, co se bude dít :)

V následujícím kvízu, Kvíz - Animace zbraně a střelba na nepřítele v Unity3D, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

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

 

Předchozí článek
3D střílečka v Unity - Ovládání animací
Všechny články v sekci
Tvorba 3D her v Unity
Přeskočit článek
(nedoporučujeme)
Kvíz - Animace zbraně a střelba na nepřítele v Unity3D
Článek pro vás napsal Tomáš Brabec
Avatar
Uživatelské hodnocení:
22 hlasů
Hodně zdaru programátoři všeho druhu,doufám ,že nikdy nezažijete nudu.
Aktivity