8. diel - 3D strieľačka v Unity - Streľba na nepriateľa
V minulej lekcii, 3D strieľačka v Unity - Efekty streľby , sme si urobili efekt streľby, zvuk výstrelu a pridali si mieridlá.
V dnešnej lekcii budeme programovať streľbu. Keď stlačíme ľavé tlačidlo, tak sa nám spustí animácia výstrelu a zároveň sa posunie objekt, na ktorý mierime, v smere nášho výstrelu. Všetko bude vyzerať nejako takto:
Spôsoby implementácie streľby
Streľba sa v Unity 3D sa dá implementovať mnohými spôsobmi. Poďme si predstaviť tie najzákladnejšie a vybrať pre nás ten najlepší.
Guľka sa skriptom
Ako príklad si uveďme možnosť vytvoriť ( "spawnout") guľku po stlačení ľavého tlačidla myši. Táto guľka by mala na sebe prichytený skript, ktorý by ju okamžite po vzniku pridával silu v smere, ktorým je namierená. Táto možnosť je zložitejšia a komplexnejšia pre našu hru. Pracuje sa v nej veľa s rotáciami objektu a získavaním smere.
Raycast
Druhá možnosť, ktorú Unity 3D ponúka a je často využívaná, je urobiť si polpriamku, ktorá vychádza zo zbrane a mieri na miesto, kam sa hráč pozerá:
Užíva sa k tomu metóda Raycast()
, ktorú by sme mohli do
slovenčiny preložiť ako "vyšli lúč" alebo "vyšli polpriamku". Táto
metóda má mnoho parametrov a nachádza sa v triede
Physics
. My zadáme iba tri parametre:
- pozície, odkiaľ má vychádzať naše polpriamka
- smer - už sme si povedali, že bude smerovať na miesto,
kam mierime. Tento smer je rovnaký ako smer, ktorým sa pozeráme. Alebo ak
rovnaký smer, aký má naša kamera. A ako získať smer, ktorým "sa pozerá"
naša kamera? Pomocou
objekt.transform.forward
, kedyobjekt
tu bude naša kamera. - naše premenná, do ktorej sa budú ukladať informácie o
objekte, ktorý naše polpriamka trafí. Táto premenná je typu
RaycastHit
.
Teraz sa môžeme vrhnúť na reálne činy, keď už vieme ako to funguje a čo potrebujeme urobiť.
Príprava na programovanie
Najskôr potrebujeme na niečo strieľať. Vytvoríme si nový objekt
Cube a prichytíme na neho komponent Rigidbody
.
Vďaka tomu ju potom môžeme pridať silu v smere nášho výstrelu a na objekt
sa budú aplikovať fyzikálne zákony.
Najskôr zo všetkého kliknite pravým tlačidlom niekde na voľnú oblasť v záložke Hiearchy, po rozrolovanie ponuky zvolíme možnosť 3D Object a potom možnosť Cube. Novovzniknutý objekt si môžete pomenovať akokoľvek, názov nebude mať žiadny vplyv na náš kód:
Ja som si svoju kocku pomenoval Target
. Teraz klikneme na kocku
ľavým tlačidlom a pozrieme sa do záložky Inspector. Tu
klikneme na tlačidlo Add Component, napíšeme
Rigidbody
a klikneme na Rigidbody
vo výsledkoch
vyhľadávania.
Pozor, nevyberiete omylom Rigidbody2D
, ktoré je
určené pre 2D
hry ! Inak vám pohyb nebude fungovať.
Klikneme ľavým tlačidlom na záložku Transform a
vložíme súradnice, napr: 5
, 1
, 5
alebo
aké si vy sami zvolíte, aby bola kocka niekde príhodne umiestnená:
V novo pridané komponente Rigidbody
nemeňte žiadne hodnoty.
Ak si s tým budete chcieť pohrať, tak odporúčam až po tvorbe nášho
skriptu pre streľbu. Jednotlivé kolónky v tejto komponente ako napríklad
Mass alebo ak hmotnosť ovplyvní, aký bude mať vplyv náš
výstrel na tento objekt.
Posledné, čo nám zostáva, je upraviť vzor objektu, ktorý budeme vytvárať vždy po výstrele. Tento objekt nám bude tvoriť efekt zásahu. Efekt je už hotový a máme ho importovaná spolu so všetkými vecami z nášho balíka. Stačí kliknúť ľavým tlačidlom myši na priečinok Low Poly F ... v záložke Project, potom kliknúť na Prefabs -> Example_P ... -> Bullet_Imp ... a tu dvakrát kliknúť na súbor Metal Imp ..., čo je úder na kov.
Vedľa objektu Metal Impact Prefab
klikneme na sipecka a tým
rozroluje podobjektoch. Vyberieme podobjektoch
Metal Bullet Hole Particle
a deaktivujeme celý podobjektoch
kliknutím na štvorček vedľa názvu. To preto, že keď by sme podobjektoch
nechali aktívne, po výstrele by sa nám objavil nepekný model "diery po
výstrele" v objekte. Nám stačí mať tu len aktivovaný prvý podobjektoch,
ktorý zaisťuje iskry a zvuk zásahu. Schválne si môžete nechať
podobjektoch aktívny obaja a rozhodnúť sa, či sa vám efekt páči a alebo
nie:
Skript EnemyHealth
Teraz nášmu objektu Target
pridáme ešte nový skript
EnemyHealth
, ktorý bude na každom našom kedy vytvorenom
nepriateľovi. Tento skript bude zisťovať koľko má daný nepriateľ, na
ktorom je náš skript, životov a ak bude mať nulu, tak sa ten daný objekt
zničí.
Ľavým tlačidlom klikneme na objekt Target
a pozrieme sa do
záložky Inspector. Tu klikneme na tlačidlo Add
Component a vpíšeme názov nášho skriptu EnemyHealth
.
Klikneme na tlačidlo New Script a potom už len na
Create and Add a skript je pridaný.
Skript shoot
Ľavým tlačidlom klikneme na náš objekt s názvom
Assault_Rifle_01_FPSController
. Potom v záložke
Inspector klikneme na tlačidlo Add Component
a napíšeme shoot
. Klikneme na tlačidlo New
Script potom už len na Create and Add a máte
hotovo:
Následne už len dvakrát klikneme na náš skript shoot
a tým
ho otvoríme.
Kód
Obsah skriptu bude nasledujúci:
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ý, prejdite si ho. Opäť tu máme niekoľko vecí k podrobnejšiemu vysvetlenie.
RaycastHit.normal
normal
je premenná typu Vector3
. Objekt, keby bol
kolmý k tomu, čo sme pomocou neviditeľnej polpriamky ray trafili, by mal smer
rovnaký ako je hodnota premennej normal
(je to teda zvislej
polohy). Nasledujúci obrázok by vám to mal pomôcť pochopiť:
Túto premennú má každá polpriamka ray.
LookRotation()
nám vráti hodnotu vo forme Quarterion (rotácie),
ktorú by sa tým smerom daný objekt pozeral.
Skript EnemyHealth
Uveďme si aj 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čí } } }
Inicializácia
public
premenných v Unity Editore
Teraz, keď sme si vytvorili kód, ktorý nám všetko riadi, nastavíme
ešte hodnoty jednotlivým public
premenným. U nášho nepriateľa
je to hodnota životov au nášho skriptu pre streľbu to sú:
- dostrel zbrane
- sila, ktorá pôsobí na nepriateľa
- vzor efektu
- poškodenie, ktoré mu udelí
Premenné skriptu shoot
Klikneme ľavým tlačidlom na objekt
Assault_Rifle_01_FPSController
. V záložke
Inspector sa nám zobrazí všetko, čo je na tomto objekte
prichytené za komponenty. Nás zaujíma komponenta shoot
, ktorá
je náš skript. Tu vidíme štyri od seba oddelená políčka s názvami:
dostrel, Sila, poškodený, Efekttrefy. Táto políčka
predstavujú rovnomennej premenné v našom skriptu. Podľa toho, aké im
nastavili hodnoty, sa hra bude správať. Keď nastavíte premennú
Silá na 5000
, tak nám objekt, na ktorý
vystrelíte a má Rigidbody
, odletí zo zorného poľa:
Ja som zvolil hodnoty:
- Dostrel:
20
, - Silá:
100
, - Poškodené:
20
.
Pre premennú Effekttrefy musíme zvoliť náš skôr upravený objekt v ktorom máme efekty. Ako prvý ho nájdeme opäť v záložke Project. Potom ho myšou pretiahneme do voľného poľa s nápisom None (Game Object) vedľa názvu Efekttrefy. Tým sa nám herné objekt priradí do tejto premennej.
Druhý spôsob je kliknúť na koliesko vo voľnom poli s
nápisom None (Game Object) a napísať do vyhľadávacieho
okienka, ktoré nám vyskočí: Metal Impact Prefab
a potom na
vyhľadaný objekt kliknúť ľavým tlačidlom.
Premenné skriptu
EnemyHealth
Klikneme ľavým tlačidlom na nášho nepriateľa, v mojom prípade
pomenovaného Target
. V záložke Inspector
následne uvidíme náš skript, ktorý je na našom nepriateľovi prichytený.
Skript sa volá EnemyHealth
. Skript by mal mať viditeľnú
premennú život. Tento ukazovateľ, ako ste už pochopili,
určuje nepriateľovho zdravie. Čím vyššia hodnota, tým viac výstrelov
vydrží. Ja mám nastavenú hodnotu 100
:
Skúška strieľanie
Teraz máme všetko nastavené a môžeme spustiť hru:
Skúste si schválne meniť hodnoty u komponenty Rigidbody
prichytené na našom nepriateľovi a sledujte, čo sa bude diať:)
V ďalšej lekcii, 3D strieľačka v Unity - Úprava terénu , sa naučíme upravovať terén, pridávať stromy a trávu.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 229x (1.74 kB)