Unity3d FPS Tutorial, czyli tworzymy własną grę FPS od podstaw z wykorzystaniem silnika Unity3d.

Temat: Kamera z bronią i strzelanie

Spis treści

Jeżeli nie używałeś do tej pory Unity3d:

#0 – Podstawy Podstaw

FPS Tutorial:

#1 – Tworzenie nowego projektu i narzędzie terenu

#2 – Sterowanie postacią

#3 – Życie, pancerz i wytrzymałość postaci

#4 – Regeneracja życia i energii. Efekty trafienia

#5 – Kamera z bronią i strzelanie

#6 – Przeładowanie broni i amunicja

#7 – Zbieranie przedmiotów

#8 – Druga broń

#9 – Rzut granatem i seria z karabinu

#10 – Celowanie i dziury po kulach

#11 – Przeciwnik z prostym AI, sztuczna inteligencja

#12 – Animacja postaci przeciwnika. Animator

#13 – Menu główne gry. GUI

#14 – Ostatnie szlify i budujemy projekt

Teoria

Mamy już poruszającą się, żywotną postać. Czas sprawić, żeby mogła strzelać! Teoria jest tak oczywista, że szkoda tekstu na nią.

Przygotowanie

Potrzebujemy modelu broni, dźwięku wystrzału i tekstury celownika. Aby twoje życie było piękniejsze, paczkę z tym „ekwipunkiem”, możesz pobrać stąd:

Tutorial_05_assets

Paczka particles z Unity 4.0

Zaimportuj wszystkie pliki do gry, umieszczając je w odpowiednich folderach. Zwróć uwagę na to, żeby pliki pistol.dae i texture.jpg zaimportować razem, ponieważ dotyczą modelu broni.

Ostatnia rzecz, to import paczki Particles ze standardowych assetów, jeśli jeszcze tego nie zrobiłeś. Można to zrobić przez: [Assets -> Import Package -> Particles]

Przygotowanie broni

Pierwszy krok, to dodanie modelu broni do sceny. Ustawiamy go od razu jako child obiektu MainCamera, który jest już childem obiektu FirstPersonController. Wystarczy przeciągnąć nazwę obiektu na drugi obiekt, aby to zrobić.

Ustawienie obiektu Gun jako childa obiektu MainCamera
Ustawienie obiektu Gun jako childa obiektu MainCamera

Teraz zresetuj ustawienia broni, aby to zrobić, klikamy na koło zębate przy komponencie transform i wybieramy reset. Teraz trzeba ustawić broń tak, by wyglądała naturalnie i tak, jak przyzwyczaiły nas do tego gry FPS.

Ustawienia położenia broni
Ustawienia położenia broni

Teraz z folderu Standard Assets/Particles/Misc, wybieramy efekty cząsteczkowe o nazwie Sparks. Przypisujemy go jako Child obiektu Gun, czyli naszej broni. Znów musimy zmienić ustawienia komponentu transform dla obiektu Sparks, tak aby iskry leciały z lufy broni. Najlepiej zrobić to sówkami z podglądem z gry, bo nie ma to być wartość co do centymetra, a dobrze wyglądająca optycznie. Dodatkowo w komponencie Elipsolid Particle Emiter zmieniamy wartość Max Energy na 0.1, oraz zaznaczamy Play One Shot, co zablokuje zapętlenie się emisji. Ogólnie ustawienia cząsteczek powinny wyglądać tak, oczywiście jeśli korzystasz z dostarczonych przeze mnie assetów:

Ustawienia emisji efektów cząsteczkowych
Ustawienia emisji efektów cząsteczkowych

Gry mamy to wszystko, czas utworzyć skrypt. Nazywamy go Shooting.cs i od razu dodajemy do obiektu Gun. Wchodzimy w edycję skryptu.

Strzelanie

Zaczynamy od deklaracji zmiennych:

  •  pistolShot – będzie przetrzymywać dźwięk wystrzału broni. Jest to zmienna publiczna, więc dźwięk wybierzemy z poziomu Unity.
  • range – Zasięg broni
  • pistolSparks – Przetrzymuje obiekt efektu cząsteczkowego
  • fwd – Wektor, określający przód, czyli gdzie gracz patrzy
  • hit – jest to zmienna typu RaycastHit, czyli pozwoli przetrzymywać informacje na temat kolizji spowodowanych rzucaniem promienia.

Dodatkowa Wiedza
Raycasting

Jest to metoda wykrywania kolizji, która polega na tym, że „wystrzeliwujemy” promień z pewnego punktu na pewną odległość. Jeżeli promień trafi na jakiś obiekt, mamy kolizję. Jeżeli nie, kolizji nie ma.

Jest to jego główna różnica względem typowych metod wykrywania kolizji, polega właśnie na tym, że nie mamy do czynienia z obszarem, a jedynie promieniem.


Zauważyłeś pewnie, że wykorzystujemy AudioClip, ale nie dodaliśmy nigdzie źródła dźwięku. Dlatego na samym początku skryptu – przed deklaracją klasy – dodajemy takie coś:

Ta jedna prosta linijka, sprawia, że skrypt wymaga od obiektu, do którego jest przyłączony posiadania komponentu AudioSource. Jeżeli go nie ma, zostanie automatycznie dodany.

Jeszcze nie koniec przygotowań. W funkcji Start, potrzebujemy ustawić kilka opcji:

Po pierwsze chowamy kursor myszy. Nie będzie to widoczne w edytorze, ale po zbudowaniu gry. Robimy to dlatego, że ja osobiście nie przypominam sobie gry FPS, w której mieliśmy widoczny kursor myszy. Następnie odnajdujemy nasze efekty cząsteczkowe, od razu zatrzymując ich emisję. Gdybyśmy tego nie zrobili, rozbłyski wystrzału migałby od samego początku gry w nieskończoność. Ostatnia rzecz, to ustawienia clipu na naszą zmienną, publiczną. Oznacza to, że nasze AudioSource, w przypadku uruchomienia, odtworzy właśnie ten dźwięk.

Czas na samo strzelanie:

Po pierwsze określamy gdzie jest przód. Przyda się to przy rzucaniu promienia.

Następnie, mamy klasycznego ifa, sprawdzającego czy nacisnęliśmy przycisk strzału. Jeżeli się to stało, to pierwsze dwa kroki to emisja cząsteczek i odtworzenie dźwięku.

Kolejny if to rzucenie naszego promienia. Pierwszy parametr to położenie startowe, czyli nasza kamera, a dokładniej jej środek. Drugi to kierunek wystrzału (dlatego, potrzebowaliśmy zmienną określającą położenie), ostatnia zmienna to zmienna RaycastHit, która przetrzymuje dane o kolizji. Zwróć uwagę na słowo kluczowe out, które jest wymagane w C#.

Teraz, gdy wiemy, że pojawiła się kolizja, czas sprawdzić z czym kolidujemy. My na tą chwilę dopuszczamy dwa typy. Po pierwsze, gdy trafiony obiekt, ma tag enemy i jest w zasięgu, zakładamy, że trafiliśmy przeciwnika. Jeżeli trafiliśmy coś będącego w zasięgu, ale innego niż z tagiem „enemy”, zakładamy że trafiliśmy ścianę. W przeciwnym wypadku, nie reagujemy.

Wróćmy teraz do Unity. Zaznacz obiekt broni i uzupełnij zmienną PistolShot dźwiękiem wystrzału (np. tym dostarczonym przeze mnie na początku). Wystarczy przeciągnąć.

Użyliśmy tagu Enemy, ale w sumie go nie ustawiliśmy. Wchodzimy w menu: [Edit -> Project Settings -> Tags and Layers]. Teraz zwracamy naszą uwagę na penel Inspector, gdzie pojawiły się nowe opcje. Najpierw rozwijamy pozycję Tags, klikając w trójkąt przy nim. Klikamy w pierwszy wolny input i wpisujemy tam tag Enemy.

Rozwijamy też pozycję Layers. Również w pierwszym wolnym miejscu dopisujemy warstwę Guns. Będzie to nam potrzebne później.

Ustawienia tagów i warstw
Ustawienia tagów i warstw

Możesz teraz dodać do sceny dwa cuby i jednemu ustawić tag „enemy”. Uruchom grę i postrzelaj w obiekty, patrząc na to co zwraca konsola. Powinny się pojawić odpowiednie komunikaty, które ustawiliśmy w kodzie.

Przenikanie broni

Bawiąc się grą, mogłeś zauważyć, że broń przenika przez ściany. Możemy temu zaradzić prostym trikiem. Dodaj do sceny nową kamerę. [GameObject -> Create Other -> Camera]. Nową kamerę nazywamy GunsCamera i ustawiamy jako child MainCamery. Resetujemy jej ustawienia dla komponentu transform (Koło zębate -> Reset). Teraz czas zmienić kilka parametrów samej kamery:

  • Clear Flags -> Depth Only – Dzięki temu, kamera rysuje tylko elementy gry, pomijając np. skybox czy kolor tła.
  • Culling Mask -> Wybieramy tylko naszą warstwę Guns. Dzięki temu, kamera rysuje wszystko co znajduje się na tej warstwie i nic po za tym.
  • Depth -> 80 – De facto, nie ważne jaka będzie to liczba, byleby była wyższa od tego parametru dla MainCamera. Jest to jak by priorytet kamer. Czyli im wyższy, tym obiekty z tej kamery będą renderowane bardziej z przodu.
Dodatkowa Wiedza
Depth – Przykład

Gdy nasza kamera z Depth 0 ma narysować drzewo, a w tym samym miejscu kamera z Depth 80, ma rysować broń, wyrenderowana zostanie broń, bo ta kamera ma wyższe Depth.

Ustawienia obiektu GunsCamera
Ustawienia obiektu GunsCamera

Skoro GunsCamera ma rysować broń, to MainCamera nie powinna tego robić, aby nie było duplikatów. Dlatego wybieramy obiekt MainCamera i w opcji Culling Mask, odznaczamy warstwę Guns.

Ostatni krok, to wybranie obiektu broni i wybranie mu warstwy Guns.

Warstwa dla broni
Warstwa dla broni

Celownik

Tutaj sprawa jest banalnie prosta. Na chwilę wracamy do skryptu. Dodajemy dwie zmienne na samym początku:

Pierwsza to tekstura 2D, samego celownika. Druga, określa pozycję celownika.

Kolejny krok, to wyśrodkowanie celownika:

Dzięki zabiegowi w pierwszych linijkach otrzymujemy środek ekranu. Gdybyśmy wzięli samą połowę ekranu gry, wtedy na środku mielibyśmy lewy górny róg tekstury. Dlatego odejmujemy też połowę szerokości i wysokości samej tekstury.

Zostało narysować teksturę, dlatego dodajemy:

Chyba nie trzeba tutaj nic tłumaczyć, pierwszy parametr to pozycja, drugi to sama tekstura.

Wracamy do Unity i znajdujemy naszą teksturę celownika. Zaznaczmy mu opcję Alpha Is Transparent, klikamy Apply i przeciągamy do zmiennej w skrypcie.

Dodanie tekstury celownika
Dodanie tekstury celownika

W tej chwili system strzelania z celownikiem powinny działać perfekcyjnie.

 Poprzednia część <- #4 –  Regeneracja życia i energii. Efekty trafienia

Następna część -> #6 – Przeładowanie broni i amunicja

  • Qiuer

    Robię wszystko jak w poradniku, ale przy pierwszym kodzie występuje mi błąd: error CS0116: A namespace can only contain types and namespace declarations
    Nie wiem co zrobić pomóż..

    • Kod nie pokazuje całego pliku. Na początku może Ci brakować linii, które są wstawiane domyślnie przy utworzeniu skryptu, czyli:
      using UnityEngine;
      using System.Collections;
      Ew, kod mogłeś wstawić po za klasą. Całość powinna wyglądać tak (Ja tego kodu nie podaję, bo jest on automatycznie generowany):

      using UnityEngine;
      using System.Collections;

      public class Shooting : MonoBehaviour {
      // Tutaj kod
      }

    • Qiuer

      Dzięki już to ogarnołem.

  • Pingback: Unity3d FPS Tutorial #12 - Animacja postaci przeciwnika. Animator | mWin GameDev()

  • Pingback: Unity3d FPS Tutorial #8 - Druga broń | mWin GameDev()

  • Vindict

    Kiedy skrypt na strzelanie przypisuje do broni to działa on tylko gdy broń dotyka celu (chyba chodzi o to, że inaczej raycast trafia na broń z której jest generowany). Kiedy przypisze go do kamery to działa jak trzeba ale utrudnia to mocno napisanie skryptu na zmianę broni.

    • Faktycznie występuje taki problem, który skorygowałem dopiero później. Poprawnie, skrypt powinien być przypisany do broni, ale promień rzucany z kamery. Tzn.:

      Transform tf = transform.parent.GetComponent();
      Physics.Raycast(tf.position, fwd, out hit)

      Dzięki temu promień leci w środek tego co widzi gracz, a wszystkie statystyki są zależne od broni. Jak mówię, w późniejszych częściach jest podany cały skrypt bez błędów. Tutaj muszę dokonać poprawek.

  • Tajniak

    Niestety, nie jest to tutorial przygotowany pod unity 5…
    Dasz radę to poprawić, czy niestety będę musiał poszukać czegoś innego?
    Tak czy siak, dzięki :)

    • Owszem, nie jest dedykowany piątej wersji, ale również pod nią działa. Jeśli pojawiały się jakieś konkretne problemy starałem się je poprawiać i niektóre części kursu mają podzielone fragmenty dla Unity 4.6 i dla 5.0

      Raczej całego kursu nie będę zmieniał – byłoby to trochę pracochłonne i bezcelowe, bo jak mówię, skrypty raczej działają, a tam gdzie były większe różnice dodałem adnotację. Jednak kurs z użyciem Unity 5.0 będę tworzył w najbliższym czasie na przykładzie gry Androidowej.

    • Tajniak

      Będę wdzięczny i będę czekał na to :)
      Powodzenia!

  • NeverOn

    Siemka, mam problem i to nie pierwszy raz z akcją podczas gry ;-;

    Chodzi dokładnie o to że jak w poprzednich tutkach było o obrażeniach od klawisza ‚P’ to włączało mi to Pauze
    Identycznie mam teraz podczas próby strzelania po prostu włącza mi się Pauza nieważne jaki to klawisz efekt ten sam

    Skrypt mam dobrze napisany (sprawdzałem 3x)

    Wszystkie efekty pod broń są podpięte oraz wszystko jest prawidłowo ustawione

    Dodatkowo podczas klikania w przycisk ‚Play’ aby zobaczyć efekty pracy automatycznie włącza mi się ta Pauza

    • Prawdopodobnie pojawia się jakiś błąd lub ostrzeżenie. Włącz w konsoli wyświetlanie wszystkich typów powiadomień (3 przyciski w prawym górnym rogu tego okna) i wtedy uruchom grę.

    • NeverOn

      Zrobiłem jak kazałeś są 3 błędy:
      * PistolSparks – 2 błędy NullReferenceException: Object reference not set to an instance of an object
      NullReferenceException: Object reference not set to an instance of an object
      Są to błędy z odtwarzaniem cząsteczek wystrzału lecz nie wiem o co chodzi skrypt już skopiowany od Ciebie i nadal nic

      I ostatni pojawił się HitTexture z sterowania postacią:
      UnassignedReferenceException: The variable hitTexture of PlayerStats has not been assigned.
      Lecz gdy chcę dodać tam jakąś texturkę do tego to nic nie idzie

      I problem dzisiaj ten sam, wciąż podczas wciskania P oraz Fire1 gra się wstrzymuje i nic się nie dzieje

    • NeverOn

      Ok poprawiłem jednak był błąd z niedodaniem 1 opcji do skryptu :p zwykłaliterówka

    • Czyli już wszystko działa?

    • NeverOn

      Tak :) dzięki za podsunięcie pomysłu aby sprawdzić 4x

  • Paweł Jamroziak

    Problem pojawia się już przy wrzuceniu broni na scenę. Po pierwsze pistolet nie ma tekstur.. Jest sam model mimo że plik z teksturą jest w tym samym folderze. Po drugie, gdy połącze kamere z bronią to jej nie widać. Gdy naciskam dwa razy na model broni to przenosi mnie do jej podglądu…

    • Ten model jest nieco oporny. Mi osobiście załadował się poprawnie po kilku próbach importowania. Możesz spróbować użyć innego modelu najlepiej z Asset Store.

    • Paweł Jamroziak

      Importować po prostu poprzez wrzuceniu go do folderu Materials w Win?

    • Ta metoda może być nieskuteczna. Spróbuj wybrać z menu górnego Import Asset.

    • Paweł Jamroziak

      Udało się. Wystarczyło zrobić tak: wybrać model Pistol — > Wybrać w menu Inspector „Select” — > W Material Naming wybrać „From Model’s Materials”. Dopiero wtedy została nałożona tekstura na model.

      Model jest prze ogromny. Przeskalowałem go do: 0.001

  • xSmouok

    Mój pistolet musi dotykać obiektu aby wywołał „Trafiony przeciwnik” w konsoli
    Pomoże ktoś?

    • W ifie jest taki fragment „hit.distance < range". Zmienna range jest deklarowana wcześniej i określa zasięg broni. Jeśli masz wartość tej zmiennej ustawioną na jakąś niską wartość, to może być konieczne podejście bardzo blisko.

    • xSmouok

      private float range = 1000.0f;

      Tak ustawiłem.
      Ale nadal muszę podchodzić do obiektu żeby wykrył strzał

    • Jeżeli przeciwnik posiada collider w trybie is Trigger, możliwe, że trafiasz w niego. Albo opcja druga, nie celujesz tam gdzie chcesz.
      1) W opcjach Edit -> Project Settings -> Physics i tam powinna być opcja Raycast Ignores Triggers – albo mniej więcej coś takiego (nie pamiętam co do słowa), wystarczy zaznaczyć opcję.
      2) Użyj funkcji Debug.DrawRay. http://docs.unity3d.com/ScriptReference/Debug.DrawRay.html
      Po uruchomieniu gry w oknie Scene będziesz mógł zobaczyć gdzie faktycznie celuje Twój promień.

    • xSmouok

      Czyli przeciwnik powinien mieć zaznaczoną opcję is Trigger w coliderze?

    • To zależy do czego on jest. Jeśli chodzi o Collider, który ma sprawić aby nie dało się przez przeciwnika przejść, to nie powinien. Jeśli ma łapać jakieś zdarzenie w okolicy przeciwnika to powinien.

    • Grzegorz Zielonka

      Mam ten sam problem. Wykonanie wszystkich czynności polecanych przez Pana nie przynosi skutku. Proszę o pomoc.

    • Możesz pokazać screeny okna inspektor dla obiektu przecinika, oraz obiektu w którym masz skrypt Shooting.cs, oraz sam kod tego skryptu? (Najlepiej przez pastebin).

  • Igor Cizewski

    Na Unity 5 jest zupełnie inaczej :/

    • Mimo, że poradnik był pisany na wersję 4.6 to muszę się nie zgodzić, bo w kwestii skryptów niewiele zostało zmienione. Jeżeli napiszesz jaki fragment nie działa, wtedy będę mógł jakoś pomóc.

    • Igor Cizewski

      Nie może znaleść Particle Emittera.

    • Jeżeli tworzysz na Unity w wersji 5.0 lub wyższej, użyj dowolnego efektu cząsteczkowe z paczki PartliceSystem. Skrypt powinien działać, jeśli wybrany efekt cząsteczkowy będzie miał np. Ellipsoid Particle Emitter.

    • Igor Cizewski

      No właśnie mam w tym problem że nie chce mi znaleść Emittera, używam Flare zamiast Sparks, jutro spróbuje od nowa zabrać się za skryp Shooting ps. Audio działa itp ale żeby w konsoli pojawiło się „Trafiony „Przeciwnik broń musi być przed nim.

  • Jakub Mazur

    Witam. Piszę w sprawie paczki Participles z początku wpisu. Problem polega na tym, że w Unity w wersji 5.1.2f1 nie ma owej paczki, a w tych co są nie ma obiektu Gun. Proszę o pomoc. Pozdrawiam.

    • Jest za to paczka ParticleSystem, w której znajdziesz masę różnych efektów (w tym też iskry), które są w sumie tym samym.
      Obiektu Gun nie ma i nie będzie, bo jest to obiekt przygotowany przez nas. Na początku wpisu podaje link do paczki z modelami, możesz też pobrać dowolny inny model broni.

    • Jakub Mazur

      Dziękuję, faktycznie jest. Pozdrawiam.

  • Jakub Mazur

    Witam. Piszę w sprawie skryptu Shooting.cs. Problem polega na tym, iż w owym skrypcie funkcja Update() się nie włącza. Proszę o pomoc i szubką odpowiedź. Pozdrawiam.
    Shooting.cs: https://rapidu.net/8595419929/Shooting.cs

    • Funkcja Update nie działa w ogóle, czy jakiś jej fragment? Jeśli w ogóle, to jedyną opcją może być fakt, że nie jest dodana do jakiegokolwiek obiektu.
      Jeżeli nie działa jakiś fragment, warto było wiedzieć jaki.
      Jeśli nie wiesz co działa, a co nie, to w bloki kodu wstaw sobie Debug.Log z różnymi tekstami, żeby zidentyfikować, na której części kodu wykłada się program.

  • wolerak

    Mam problem z Particle System. Na unity 5.0 dodałem Emiter do prefaba, ale i tak cząsteczki się nie pokazują. Co mam zrobić?

    • Ciężko powiedzieć przy takiej ilości danych. Ale sam Emiter czy jakieś gotowe efekty cząsteczkowe ze standardowych assetów?

    • wolerak

      Pobrałem Assest z internetu i był przedstawiony jako prefab Particle Sytem bez emitera, więc dodałem taki jak ten, który przedstawiłeś w tej części.

    • Prawdopodobnie problemem jest sam asset. Proponuję wrzucić do sceny jakiś emiter cząstek ze standardowych assetów Unity i porównać komponenty w obu i uzupełnić ewentualne braki.
      Może się jednak okazać, że pobrany asset jest źle zrobiony i zwyczajnie nie będzie działał.

  • Shym

    Witam ,mam problem ze skryptem shooting.cs.
    Błędy jakie mi wyskakują w Unity:
    NullReferenceException: Object reference not set to an instance of an object Shooting.Start() (at Assets/Scripts/Shooting.cs:17)
    W lini 17 mam napisane:
    pistolSparks.GetComponent().emit = false;

    Drugi błąd:
    Taka sama treść tylko zmiana w … of an object Shooting.Update() … w 27 lini.
    W 27 lini mam napisane:
    pistolSparks.GetComponent().Emit();

    Postac kodu różni się trochę od tego co jest w tutorialu ,dlatego ,że Unity zrobił mi API update ,aby mógł działać ten skrypt.
    Proszę o pomoc. Z góry dziękuję.

    • Shym

      Jak wchodzę w tryb Play i nacisnę LPM ,aby strzelić to w konsoli wyskakuje mi ta 27 linia ,którą opisałem wcześniej w Shooting.Update().

    • Rozchodzi się o to, że Twoja zmienna pistolSparks albo nie istnieje, albo nie posiada komponentu particleemitter.
      1) Sprawdź, czy na pewno podałeś i zdefiniowałeś zmienną pistolSparks (czy posiada wartość)
      2) Sprawdź, czy obiekt pistolSparks posiada komponent emitera.
      3) Sprawdź wielkość liter w zmiennych. Przykładowo, jak szukasz ParticleEmittera, a wpisujesz particleemitter, to go nie znajdziesz przez zmianę wielkości liter.

    • Shym

      I w tym mam jeszcze jeden problem ,bo nie moge znaleźć żadnego emitera i dać go po tem do pistol w hierachy.

    • Wiele różnych efektów cząsteczkowych powinno być dostępnych w standardowej paczce Unity – Particles.

    • Shym

      private GameObject pistolSparks; – chyba jest zdefiniowane

      Jak wchodzę w ParticleSystems to mam:
      -materials,
      -prefabs,
      -scripts,
      -shaders;
      -textures.
      Niestety tych emiterów nie ma ,albo źle szukam. W wyszukiwarce wpisywałem zwracając uwagę na wielkość liter.

    • private GameObject pistolSparks;
      Ale nie ma przypisania wartości do zmiennej.

      W folderze Prefabs. Nie będzie to ten sam efekt co u mnie (bo zmieniły się między wersjami nieco) ale jakiś sobie dopasujesz.

    • Sprawa jest banalnie prosta o czym sugeruje sam błąd. Masz 2 rozwiązania:
      pistolSparks jest niezadeklarowane. Odpowiada za to normalnie linijka:
      pistolSparks = GameObject.Find(„Sparks”);
      Na taki błąd trafisz, jeśli skrypt nie umie odnaleźć obiektu Sparks. Wtedy albo go nie dodałeś, albo nazywa się u Ciebie inaczej (wielkość liter może mieć znaczenie).
      Drugi wariant to fakt, że Twój obiekt Sparks istnieje, ale nie posiada komponentu Particleemitter. Musisz komponent dodać.

    • Marcin Iwanowski

      z kąd wzioć sparksy z tych assetów co podłałeś? bojak je ściągnąłem to nie ma tam żadnej grafiki tylko dźwięk

    • Pochodzą ze standardowych assetów do Unity 4.6. Ale możesz wykorzystać dowolne inne efekty cząsteczkowe.

  • Pingback: Unity3d FPS Tutorial #3 - Życie, pancerz i wytrzymałość postaci | mWin()

  • Pingback: Unity3d FPS Tutorial #6 - Przeładowanie broni i amunicja | mWin()

  • Dominik Dominik

    u mnie nie chce strzelać co źle zrobiłem?a niby wszystko działa

  • Dominik Dominik

    u mnie nie chce strzelać co źle zrobiłem? a niby wszystko działa z tym że nie wiem jak dodać ten participles system bo mam Unity 5

    • W sensie, nie możesz znaleźć odpowiedniego obiektu w assetach, czy masz jakiś inny problem?

  • Michał Krynicki

    Gdy do skryptu shooting dodaje: [RequireComponent(typeof(AudioSource))]

    public class Shooting : MonoBehaviour

    {

    }

    Unity pokazuje mi następujący błąd:

    The namespace global::' already contains a definition for Shooting’

    nie wiem jak to rozwiązać

    • Gdzieś prawdopodobnie masz już zdefiniowaną klasę Shooting, w jakimiś innym pliku lub coś. Error leci, bo próbujesz zdublować skrypt.

    • Michał Krynicki

      tylko że posiadam tylko jedną klasę Shooting.

    • Niestety kompilator jest jednoznaczny. Gdzieś w projekcie (czy to w Twoich plikach czy w bibliotekach zewnętrznych) istnieje już klasa o tej nazwie. Opcje rozwiązania są 2:
      1) Znaleźć duplikat i usunąć.
      2) Zmienić nazwę obecnie tworzonej klasy

    • Michał Krynicki

      Pojawił się kolejny problem. w poradniku jest napisane „Nową kamerę nazywamy GunsCamera i ustawiamy jako child MainCamery.” Tylko że zauważyłem że w unity 5 kamera nie jest dodawana jako Child tylko tak samo jak skrypty czy colidery i nie wiem jak zrobić by pistolet nie przenikał przez ściany.

    • Obiekt kamery to nic innego jak EmptyGameObject z dodanym komponentem kamery. :)
      Do roznych zastosowan trzeba dodac inne komponenty np. GUILayer zeby wyswietlac GUIText. Ale do tego zastosowania wystarczy sam komponent kamery w pustym obiekcie. :)

  • Dokładnie dlatego. Część skryptów się nieco zmieniła, ale kod błędu podpowiada Ci dokładnie co masz zrobić. Pierwszy błąd:

    Assets/Scripts/Shooting.cs(19,30): error CS0619: UnityEngine.GameObject.particleEmitter' is obsolete: Property particleEmitter has been deprecated. Use GetComponent() instead. (UnityUpgradable)’

    Dosłownie mówi, że parametr UnityEngine.GameObject.particleEmitter jest przestarzały i należy użyć GetComponent(). Zrób dokładnie tak i błąd z głowy.

    Linia 20 i 28 to dokładnie ten sam błąd, tylko związany z audio. Również w kodzie błędu masz napisane czym linijkę zastąpić.

    Reszta błędów powinna się po tym zmienić lub zniknąć.

  • Nie wiem czy dobrze liczę, ale chyba nie masz domkniętego nawiasu klasy.

    Wyświetlają Ci się jakieś błędy? Byłoby to bardzo pomocne w szukaniu błędu.

  • Pingback: Unity3d FPS Tutorial #1 - Tworzymy nowy projekt i przygotowujemy teren | mWin()

  • SendronGames

    Dasz link do tego sparksa?

  • Pan Diaxik

    Wyświetlają mi się dwa błędy dotyczące 18 linii kodu:

    Assets/Scripts/Shooting.cs(18,17): error CS0619: UnityEngine.Component.audio' is obsolete: Property audio has been deprecated. Use GetComponent() instead. (UnityUpgradable)’

    Assets/Scripts/Shooting.cs(18,23): error CS1061: Type UnityEngine.Component' does not contain a definition for clip’ and no extension method clip' of type UnityEngine.Component’ could be found (are you missing a using directive or an assembly reference?)

    Moja 18 linia kodu wygląda tak:

    audio.clip = pistolShot;

    Korzystam z Unity 5.2.2f1

    Edit:
    Zmieniłem linię 18 na:

    GetComponent (pistolShot);

    Teraz jest błąd:

    Assets/Scripts/Shooting.cs(18,17): error CS0308: The non-generic method `UnityEngine.Component.GetComponent(System.Type)’ cannot be used with the type arguments

    • Poprawne użycie tej funkcji to:
      GetComponent();

      czyli w Twoim wypadku będzie:
      GetComponent();

  • franek dolas

    hello, przerobiłem 5 odcinek i mam 3 pytania:
    1. jak dodać tzn gdzie znaleźć te cuby do poćwiczenia enemy/ściana
    2. mam dziwny efekt tzn moja giwera oddaje 1 strzał po odpaleniu gry a nie naciskam strzału, dalej wszystko ok
    3. mam problem z przenikaniem pistoletu, robiłem wszystko jak w tutorialu ale jednak nie działa dodam że zrobiłem tak jak mówiłeś na początku tzn. usunąłem obiekt MainCamera wiec zakładam że moją główną kamerą jest FirstPersonCharacter i właśnie do tego obiektu dodałem child GunsCamera może tu jest problem? Czy może trzeba zrobić nowy obiekt MainCamera? dodatkowo po odpaleniu gry sypie warningami:

    There are 2 audio listeners in the scene. Please ensure there is always exactly one audio listener in the scene. przypuszczam że rozchodzi się o to ze teraz mam 2 kamery bo wcześniej tez miałem tego warninga dopóki nie usunąłem MainCamera. TRINITY HELP :) i dzięki za wcześniejsze odpowiedzi.

    • 1) W menu GameObject -> 3D Object -> Cube.
      Jeśli jeszcze tego nie zrobiłeś, polecam zapoznać się z odcinkiem zerowym kursu, gdzie największe podstawy są opisane. Bez tego będzie Ci później trudno zrobić cokolwiek.

      2) Ubywa amunicji, czy tylko słyszysz dźwięk? Wynikać może to z tego, że uruchamiasz tryb gry lewym klawiszem myszki, który też odpowiada za strzał. Nie powinno to mieć miejsca. Przy czym nie do końca wiem, czym to może być spowodowane.

      3) FisrtPesonCharacter nie jest kamerą. Wewnątrz tego obiektu masz obiekt kamery głównej (MainCamera) i do niego jako child, powinieneś dodać GunsCamera.

      4) Ostrzeżenia wynikają z tego, że prawdopodobnie obie Twoje kamery mają komponent AudioListner, czyli komponent odpowiedzialny za odbieranie dźwięków z otoczenia. Usuń komponent w jednej z kamer i wszystko będzie w porządku.

  • franek dolas

    hello, pisząc odcinek zerowy kursu masz na myśli ten o nazwie „podstawy podstaw”? jeśli tak to od niego zacząłem tutorial ale nie ma tam nic o obiekcie Cube chyba że chodzi ci to że omawiasz tam zakładkę Game Object ale jakieś ustawienia tego Cube’a itp to nic nie widziałem, więc problem mam taki:

    1. dodaje obiekt Cube z Game Object pojawia mi się w Hierarchy i oknie Scene ale po odpaleniu gry go nie widze/ nie moge znalźć – może trzeba pomajstrować w ustawieniami Cube’a?

    2. z warningami o Audio Listenerze sobie poradziłem ale trzeba było usunąć Component w obiekcie Main Camera, usunięcie w FirstPersinCharacterze powoduje ze nie słysze dźwieku chodzenia/kroów/skoków

    3. problem z wystrzałem na dzień dobry po odpaleniu gry też rozwiązałem: w obiekcie Gun, oknie Inspector i zakładce Audio Source jest opcja : Play On Awake – wystarczyło odznaczyć.

    i mój główny koszmar: uznałem że coś porąbałem z tymi kamerami więc zrobiłem nowy project, wszystko śmiga/działa/żadnych błędów i warningów a nie widzę giwery po uruchomieniu gry co jest dziwne bo widzę celownik i staty.

    Moje Hierarchy wygląda tak:

    FPSController
    FirstPersonCharacter
    MainCamera
    Gun
    Sparks
    WaterProDayTime
    DirectionalLight
    Terrain
    WindZone

    Wydaje mi się że mam dwie kamery i tu jest problem bo W FirstPersonCharacter mam CameraPreview w oknie Scene i jest CameraPreview w MainCamera , dodatkowo po odpaleniu CameraPreview FirstPersonCharactera widze mape w CameraPreviw MainCamery widze moją giwere ze sparksami ale tylko na tym podglądzie po odpaleniu jej nie ma ale moge strzelać tzn słysze dźwięk strzału widze celownik i staty. Jakieś pomysły???

    • Jeżeli nie widzisz samej broni, a postępowałeś zgodnie z tutorialem, to prawdopodobnie obiekt broni masz na warstwie Gun, kiedy żadna z kamer tej warstwy nie wyświetla. Ewentualnie odpal grę mając widoczne i okno Game i okno Scene. Wtedy zobacz czy broń jest widoczna w oknie Scene, jeśli tam jej nie będzie to jest szansa, że jakiś Twój skrypt przemieszcza broń nie tam gdzie trzeba, przez to jej nie widać.

      Z Hierarchy niewiele wynika, bo nie widać tutaj relacji między obiektami.

  • Pingback: Unity3d FPS Tutorial #7 - Zbieranie przedmiotów | mWin()

  • Robror

    Wie ktoś morze, dlaczego w konsoli od razu wywala błąd ?

    • Bo wykorzystany kod jest pod wersję 4.6, a korzystasz z Unity w wersji 5 :)

      Jeśli zapiszesz kod i uruchomisz Unity, to system sam powinien Ci dostosować większość kodu, do współczesnych wersji.

    • Robror

      Ok, po napisaniu skryptu, uruchomiłem ponownie MonoDevelop, kod zostal przystosowany do Unity 5, konsola nie pokazuje błędów, Ale tym razem Unity nie chce mi ułatwić pracy i dał komunikat (Some scripts have compilation errors which may prevent obsolete API usages to get updated. Obsolete API updating will continue automatically after these errors get fixed.) Przez to nie mogę uruchomić trybu gry, a w samym skrypcie nie mam możliwości przypisać dzwięku.

    • Robror

      Udało mi się usunąć tamtejsze błędy, ale nadal nie mam możliwości przypisania dźwięku i tekstury celownika w skrypcie shooting.cs

    • Robror

      Wysyłam screen edytora, proszę zwrócić uwagę na adnotację pod skryptem shooting.

    • Błąd mówi o tym, że musisz usunąć wszystkie błędy ze skryptu, które pewnie są wypisane w konsoli (chyba, że przyciskami w prawym górnym rogu okna konsoli, wyłączyłeś ich wyświetlenie).

    • Robror

      Przy poleceniu particleEmitter.emit pokazuje, że UnityEngine.GameObject nie zawiera definicji find

    • To by się zgadzało. A jak wygląda Twój fragment kodu do którego odnosi się błąd?

    • Robror

      Cały kod wygląda tak

      using UnityEngine;

      using System.Collections;

      [RequireComponent(typeof(AudioSource))]

      public class shooting : MonoBehaviour {

      public AudioClip pistolShot;

      private float range = 10.0f;

      private GameObject pistolSparks;

      private Vector3 fwd;

      private RaycastHit hit;

      // Use this for initialization

      void Start () {

      Cursor.visible = false;

      pistolSparks = gameObject.find („Sparks”); <—-Tu występuje błąd

      pistolSparks.GetComponent().emit = false;

      GetComponent().clip = pistolShot;

      }

      // Update is called once per frame

      void Update () {

      fwd = transform.TransformDirection (Vector3.forward);

      if (Input.GetButtonDown („Fire1”)) {

      pistolSparks.GetComponent().Emit ();

      GetComponent().Play ();

      if (Physics.Raycast (transform.position, fwd, out hit)) {

      if (hit.transform.tag == „Enemy” && hit.distance < range) {

      Debug.Log ("Trafiony Przeciwnik");

      } else if (hit.distance < range) {

      Debug.Log ("Pudło");

      }

      }

      }

      }

      }

    • W Unity jest funkcja Find, a nie find. Wielkość liter ma znaczenie.

    • MatK

      mam taki sam problem, lecz gdy włacze i wyłacze visual studio to te 2 linijki kodu mi sie nie poprawiaja (uzywam unity 5 z Microsoft Visual Studio)

  • Robror

    Wystąpił u mnie błąd, braku dźwięku przy strzelaniu oraz kiedy strzelam w cube z tagiem „Enemy” nie pokazuje żadnego komunikatu.

    • Jesteś pewny że przypisałeś odpowiedni audioClip do zmiennych publicznych z poziomu Unity?

    • Robror

      Jestem pewien, po ponownym przeanalizowaniu kodu stwierdzam, że wszystko jest tak jak na tutorialu a nadal nie mam dźwięku przy strzelaniu oraz brak jakichkolwiek informacji podczas strzelania w bryłę z tagiem „Enemy”

    • Brak informacji może wynikać z za małego zasięgu broni. Może zwyczajnie pocisk „nie dolatuje”? Spróbuj zwiększyć zasięg.

      Z dźwiękiem może być trudniej coś wymyślić. Ale czy masz na pewno kompnenty AudioSouce, który wyda dźwięk i komponent AudioListner, który go odbierze?

  • Michał Krynicki

    W mojej grze są dwa pistolety jeden przenika drugi nie przenika.

    • Zakładam, ze obie Twoje kamery wyświetlają broń. Tzn. nie zmodyfikowałeś opcji Culling Mask dla kamery głównej.
      Ewentualnie masz doczepione dwie bronie, zamiast jednej, ale zakładam że to sprawdziłeś. ;)

  • Marcin B

    Witam. Zrobiłem wszystko tam jak wyżej pistolet strzela jest dźwięk ale przenika przez drzewa i komunikat że trafiłem przeciwnika jest dopiero jak wejdę w cube(pistole jest w środku) zwiększyłem range do 1000 do drzewa już z dalsza strzela i jest że trafiłem w ściane ale do cube nadal tak samo i tak samo w ziemię muszę skierować w dół żeby pistolet przeniknął. Z tagami zrobiłem tak jak wyżej.

    • Przepraszam, ale nie bardzo zrozumiałem problem. Mógłbyś opisać go nieco dokładniej?

  • Ksurix

    Ja cie gosciu nie pojmuje, W jednym poradniku tłumaczysz super fajnie i wyjasniasz a w następnym w ogóle prawie tego nie robisz, I właśnie tak jest w tym, Co z tego ze ktos przepisze skrypt nie wiedząc co on dokladnie robi i jak mozna go zastosowac innaczej?
    Chodzi o to:

    void Update ()
    {
    fwd = transform.TransformDirection(Vector3.forward);

    if(Input.GetButtonDown(„Fire1”)) {
    pistolSparks.particleEmitter.Emit();
    audio.Play();

    if (Physics.Raycast(transform.position, fwd, out hit)) {
    if(hit.transform.tag == „Enemy” && hit.distance < range) {
    Debug.Log ("Trafiony przeciwnik");

    } else if(hit.distance < range) {
    Debug.Log ("Trafiona Sciana");
    }
    }
    }
    }

    Physics w ogóle ominąłeś, nie wytlumaczyłeś vector3. Nie wytłumaczyłeś dlaczego tam jest Transform.direction itp…

    • Ksurix

      Jesli możesz to wytlumacz wszystko w tym skrypcie :)

    • Znacząca część kodu jest opisana. Ten tutorial pisałem jakieś 2 lata temu, więc wtedy uczyłem się, jak się takie rzeczy pisze, stąd pewne niedociągnięcia czy braki. Dodatkowo kod powstawał pod Unity 4.6, więc część może się nie do końca pokrywać.

      A jeśli chodzi o ten kod, to lecąc po linijce:
      – Pierwsza określa nam, gdzie jest przód obiektu. Funkcja TransformDirection, zmienia współrzędne lokalne na globalne. Czyli gdy przypisujemy broń jako childa, childa jakiegoś obiektu, to nie musimy się martwić że namieszamy – zawsze dostaniemy przód. Oczywiście to nam może zaszkodzić, jeśli w pewnym momencie stwierdziliśmy, że oś Y będzie u nas przodem. Ale nie powinniśmy tego robić.

      – If sprawdza czy kliknięto przycisk „Fire1”, który domyślnie jest lewym klawiszem myszki. Ale w konfiguracji można to zmienić.

      – Następne dwie linię, to uruchomienie emitera cząsteczek (żeby poleciały iskry przy strzale) i dźwięku wystrzału.

      – Kolejny if to rzucanie promienia (czym jest rzucanie promienia, opisałem w ramce, więc pomijam).

      – Wewnątrz tego ifa, sprawdzamy czy trafiony obiekt posiada tag Enemy, oraz czy znajduje się w zasięgu, który sobie ustaliliśmy. Łatwo to możemy ogarnąć, bo wszelkie informację na temat obiektu z którym w kolizję wszedł promień, mamy w zmiennej hit.

      – elseif wykona się, kiedy coś będzie w zasięgu, ale nie będzie miało tagu enemy.

      – Debug.Log to wypisanie na konsoli jakiegoś tekstu.

      Physics – to globalna klasa Unity, zawierająca funkcję i zmienne dotyczące Fizyki
      Vector3 – to standardowa struktura Unity, reprezentująca wektor w 3 wymiarowej przestrzeni.

      Chyba wszystko.

    • Ksurix

      Dalej nie rozumiem działania pierwszej linijki :( Nie umiem pojąć o co w niej chodzi i po co to. :(

    • Ksurix

      Siedze przy tym 3 dzien i się głowie :(

    • Ksurix

      Pierwsza linijka działa tak że obiekty podrzędne firstpersonController mają skierowany przód tam gdzie my patrzymy? Bo na serio juz nie wiem, Mi trzeba tlumaczyc chyba jak dziecku

    • TransformDirection(Vector3) jako funkcja przekształca współrzędne podanego wektora, ze współrzędnych lokalnych na współrzędne globalne.

      Czyli, w naszym wypadku, pakujemy do zmiennej fwd, wektor wskazujący kierunek w którym patrzy się postać.

      Korzystamy z tej funkcji, aby mieć pewność, że dostaniemy dobry kierunek. Bo… Skrypt przypisaliśmy do childa obiektu nadrzędnego. Child ma współrzędne globalne – czyli gdzie znajduje się w świecie, oraz lokalne, czyli gdzie znajduje się względem swojego rodzica.

      Gdy pobieramy Vector3.forward, powinniśmy dostać kierunek „w przód”, czyli zasadniczo mieć wektor wskazujący na oś Z: [0, 0, 1]. Ale child, może być np. obrócony o 90 stopni w jakąś stronę i wtedy jego lokalny przód, nie byłby przodem faktycznym. Dlatego sprowadzamy go do współrzędnych świata.

      Chyba bardziej dokładnie nie umiem tego wyjaśnić.

  • Hubert Stefan Stankiewicz

    Mam podobny problem do paru osób stąd, żeby nastąpiło wykrycie czy strzelam w ścianę czy w przeciwnika muszę „wejść” w obiekt. Próbowałem dać na końcu Update
    Debug.DrawRay(transform.position, fwd, Color.red, 2, false);
    Żeby pokazało czy przypadkiem nie strzelam w jakąkolwiek inną stronę, ale nie widać niczego nawet gdy „wejdę” w obiekt i otrzymam wiadomość, że ściana bądź przeciwnik został trafiony.

    • Pokaż swój kod (przez pastebin) oraz screen z okienka scene, kiedy zaznaczysz obiekt gracza. :)

  • Błąd wynika z tego, że „przód” pistoletu jest faktycznie z boku. Czyli tak jak rysuje Ci Twoja czerwona linia.

    Możesz to naprawić podmieniając zmienną fwd, na to:
    Transform tf = transform.parent.GetComponent();
    fwd = tf.TransformDirection(Vector3.forward);

  • lisekmiki

    Witam korzystam z unity 5.3 Gdy skończyłem pisać skrypt i włączyłem Grę z kamerą dzieją się dziwne rzeczy tzn. przekręca się na boki i trochę przenika przez drzewa

    • Możesz pokazać screen, który by pokazał o co dokładnie chodzi? :)

  • Radek Mazowiecki

    Na tym odcinku mocno się napociłem super:)
    nie wiem czy to wina wersji Unity, ale u mnie nie działa odtwarzanie strzału w taki sposób jak napisałeś. najzwyczajniej w świecie klasa audio nie obsługuje metody play
    musiałem zrobić tak

    public AudioClip pistolShot;
    private AudioSource m_AudioSource;
    w starcie
    m_AudioSource = GetComponent();
    i w update
    m_AudioSource.clip = pistolShot;
    m_AudioSource.Play();

    niemam pojęcia po jasną cholerę jest ta linijka w metodzie start?
    mimo że tworze obiekt klasy AudioSource , niemam dostępu do jego parametrów?

    i niestety nie udało mi się ogarnąć wizualnego efektu strzału niby wszystko jest ok ale jak odpalam grę to widzę rozbłysk(bez strzału), może to wina prefaba ExplosionMobile.

    • Większość problemów może wynikać z różnicy wersji Unity. Po wersji 5.0 pojawiły się nowe assety oraz zmieniła się trochę składnia skryptów.

      Jeśli masz jakieś problemy, możesz je dokładniej opisać, a spróbujemy wymyślić co poszło nie tak.

  • Carl Johnson

    Mam problem i nie wiem jak go rozwiązać. Nie mam childu main camera przy FPS controler i przez to nie mogę dodać do niego „pistol”.