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

Temat: Zbieranie przedmiotów

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

Ostatnim razem, zrobiliśmy sobie pełen magazynek. Teraz czas go napełnić, dlatego zrobimy sobie system zbierania amunicji, po wejściu na nią. Miał być też tu system zbierania nowej broni, ale doszedłem do wniosku, że ten etap, będzie wymagał trochę modyfikacji istniejącego kodu, dlatego zostawimy go sobie na oddzielny odcinek.

Przygotowanie

Potrzebny nam będzie jedynie obiekt, udający skrzynkę z bronią. Może to być zwykły cube, lub dowolny inny obiekt. Ja wykorzystałem zwykły cube z darmową teksturą.

Przygotowanie przedmiotu

Żeby całość sobie ułatwić, przygotujemy przedmiot jako prefabrykant.

Dodatkowa Wiedza
Prefabrykat

Jest to swojego rodzaju matryca obiektu. Przydatny przy dynamicznym tworzeniu obiektu. Jeżeli jakiś obiekt często występuje w grze, możemy uczynić z niego prefabrykant i właśnie prefaby wrzucić do gry. Dzięki temu, gdy coś zmienimy w prefabrykancie, wszystkie obiekty w grze, otrzymają tą zmianę.


Aby z obiektu zrobić prefab, wystarczy przeciągnąć go z okienka Hierarchy do okienka Project. Będziemy potrzebować w nim dwie rzeczy. Po pierwsze collider. Wybierz w panelu Inspector: Component -> Physics -> Sphere Collider. Od razu zaznacz w nim opcję Is Trigger, oraz zwiększ nieco jego promień (Radius), tak by był większy od obiektu. Całość powinna wyglądać mniej więcej tak:

Ustawienia colliderów dla obiektu paczki amunicji
Ustawienia colliderów dla obiektu paczki amunicji

Jak mogłeś zauważyć na screenie, drugi krok to dodanie skryptu ammopack. Utwórz go teraz i przypisz do obiektu. Od razu możemy przejść w edycję skryptu ammopack.cs. Będziemy reagować tutaj na zdarzenia wejścia w trigger. Nasz plan działania jest prosty. Jeśli ktoś wejdzie w kolizję, sprawdzamy czy to gracz. Jeśli on, sprawdzamy, czy możemy zebrać amunicję. Jeśli tak, robimy to. Magiczny kod wygląda tak:

Dodatkowa Wiedza
OnTriggerEneter

Funkcja wykonuje się, gdy jakiś obiekt wejdzie w obszar collidera danego obiektu, który ma ustawione wyzwalanie (zaznaczona opcja IsTrigger. Jeżeli opcja nie jest zaznaczona, obiekt zareagowałby na zdarzenie OnCollisionEneter.

Wyróżniamy jeszcze dwa stany. OnTrigger – który wykonuje się w trakcie trwania kolizji z wyzwalaczem oraz OnTriggerExit – który wykona się gdy opuszczamy strefę kolizji.


Najpierw sprawdzamy tag obiektu, z którym weszliśmy w kolizję (zaraz zajmiemy się ustawieniem tagu). Jeżeli nasz obiekt ma tag, Player, znaczy to że jest graczem. Warto zauważyć wykorzystanie funkcji Equals, którą poleca się przy wykonywaniu operacji porównani Stringów. Wykorzystując funkcję Find, znajdujemy obiekt Gun, który jest childem naszej kamery, dlatego zapis ze slashem. Kolejny krok to sprawdzenie, czy możemy zebrać amunicję. Służy do tego funkcja canGetAmmo w skrypcie Shooting (dopiszemy tą funkcję później). Aby się do niej dobrać, pobieramy komponent skryptu i wykonujemy funkcję. Funkcja zwraca bool (prawdę lub fałsz), dlatego nie musimy nic więcej dopisywać.

Jeśli wszystko się udało, wykonujemy funkcję SendMessage. Pozwala ona wywołać jakąś funkcję danego obiektu przez podanie jej nazwy. (Ten sposób nie jest w stanie odebrać wyniku działania funkcji, dlatego nie nadawał się do funkcji warunkowej if). Druga sprawa, to fakt, że funkcja SendMessage jako drugi parametr przyjmuje tylko jedną zmienną typu Object. Więc, aby przesłać dwie zmienne, musimy posłużyć się sztuczką i wysłać obiekt typu Vector2.

Na koniec niszczymy obiekt, tak by zniknął ze sceny gry – nie chcemy zbierać dwa razy tej samej amunicji.

W skrypcie przesyłamy dwie zmienne. Czas je dodać na początku skryptu:

Pierwsza zmienna to informacja, ile amunicji doda nam zebranie paczki. Dzięki ustawieniu jej na publiczną, możemy w scenie gry, modyfikować ten parametr dla każdej paczki oddzielnie. Druga zmienna to typ broni, dla której przeznaczona jest amunicja. Póki co go nie wykorzystamy, ale gdy dodamy kolejną broń, będzie z niego pożytek. Również publiczny, aby jeden skrypt, załatwiał nam zadanie dla każdego rodzaju paczki amunicji.

Teraz zostało lekkie poprawienie wyglądu naszych paczek. Zrobimy to tak:

Kod prosty jak koszulka dziecka. W każdej klatce, obracamy naszą paczkę w okół osi OY (która powinna być osią pionową). Dzięki temu, obiekty będą obracać się powoli wokół własnej osi.

Poprawa skryptu Shooting.cs

W naszym nowym skrypcie, używamy aż dwóch funkcji, które jeszcze nie istnieją. Czas je dodać. Przechodzimy więc do skryptu Shooting.cs męczonego w poprzednim odcinku.

Najpierw funkcja sprawdzająca, czy możemy zebrać amunicję:

Sprawa prosta. Jeśli mamy tyle amunicji, ile maksymalnie możemy mieć, to nie da się zebrać więcej (czemu graczowi ma zniknąć zapas amunicji, którego nie mógł zebrać, bo aktualnie ma maksymalną liczbę pocisków?). W przeciwnym wypadku pozwalamy mu na to.

Dodanie amunicji:

Parametrem funkcji musi być obiekt Vector2, bo tak sobie ustaliliśmy. Z racji, że w tym skrypcie operujemy intami, a Vector2 wymaga floatów, pierwszy krok to pobranie liczby amunicji jaką mamy dodać, z rzutowaniem jej na inta – int w nawiasie oznacza, że wymuszamy na obiekcie by stał się typu int, o ile to możliwe. Tzn. string „20” czy float 20.0f, zmienimy na int. Jednak String „20sda” wyrzuci błąd.

Sprawdzamy sobie, czy liczba kul jaką mamy dodać, jest mniejsza niż zapas jaki możemy zyskać. Jeśli tak, zwyczajnie dodajemy amunicję. Jeśli nie, nie pozwalamy graczowi wziąć bonusowego nadmiaru, ustalając po prostu stan amunicji na maksymalny dostępny.

Tagowanie

Nasz gracz, musi mieć tag Player, aby wszystko ładnie działało. Pierwszym krokiem, byłoby stworzenie tego tagu. Zrobilibyśmy to w panelu: [Edit -> Project Settings -> Tags and Layers]. Jednak nie musimy tego robić, ponieważ Tag Player jest tagiem domyślnym. Zostało ustawić graczowi ten tag, dlatego wybieramy obiekt First Person Controller i zmieniamy pole tag:

Dodatnie tagu "Player" do obiektu gracza.
Dodatnie tagu „Player” do obiektu gracza.

Podsumowanie

W tym odcinku, stworzyliśmy sobie system zbierania amunicji, który pozwala na szybkie dodawanie paczek. Zastosowaliśmy prefabrykant, dzięki czemu łatwiej będzie modyfikować całość. Dodatkowo, pojedyncze obiektu paczek amunicji pozwalają się łatwo modyfikować. Poznaliśmy dwie metody odwoływania się do funkcji innego obiektu, oraz poznaliśmy tagi i funkcję OnTriggerEnter.

Kolejny odcinek poświęcimy zbieraniu broni i zarządzaniu nią, czyli małym inwentarzem.

Poprzednia część <- #6 – Przeładowanie broni i amunicja

Kolejna część -> #8 – Druga broń

  • Pingback: Unity3d FPS Tutorial #4 - Regeneracja życia i energii. Efekty trafienia | mWin GameDev()

  • Vindict

    Witam. Szlag mnie trafia od tego błędu, bo wszystkie nazwy się zgadzają (sprawdzałem 10 razy)

    NullReferenceException: Object reference not set to an instance of an object
    AmmoPack.OnTriggerEnter (UnityEngine.Collider other) (at Assets/Scripts/AmmoPack.cs:17)
    to jest ta 16-sta i 17-sta linijka:

    Transform pistol = other.transform.Find(„FirstPersonController/Main Camera/pistol”);
    if(pistol.GetComponent().canGetAmmo()) {

    jeżeli nazwy są poprawne to co to może być innego?

    • Jeżeli hierarchię obiektów masz taką jak w tutorialu, to w funkcji Find, „FirstPersonController” jest zbędne.

    • Vindict

      Już próbowałem. Usunięcie tego nie pomaga

    • Możesz podesłać całą funkcję OnTriggerEnter, oraz screen okienka hierarchy z zaznaczeniem, gdzie dodane są skrypty Shooting i AmmoPack? (Oczywiście, tak żebym widział wszystkie childy).

    • Vindict

      Już mam błąd. Okazało się, że był w zupełnie innej linijce kodu niż twierdziło Unity i przez to nie mogłem go znaleźć. Zwykła literówka

    • patrix972

      A można wiedzieć co to była za literówka? bo mam ten sam błąd i możliwe ,że powód jest ten sam.

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

  • Szymon Dudzik

    Witam. Do tej pory kod działał mi bez problemu, jednak po usprawnieniu skryptu strzału (tzn. wcześniej strzał miałem przypisany bezpośrednio do broni) cały czas pojawiają się błędy. W przypadku skryptu podobnego do tego w tutorialu:

    public int zapasAmunicji = 1;

    void OnTriggerEnter(Collider other)
    {
    if (other.tag == „Player”)
    {
    Transform bron = other.transform.Find(„Player/MainCamera/RevolverWeapon”);
    bron.SendMessage(„DodajAmunicje”, zapasAmunicji);
    Destroy(gameObject);
    }
    }

  • Szymon Dudzik

    Witam. Do tej pory kod działał mi bez problemu, jednak po naniesieniu kilku poprawek i usprawnieniu skryptu strzału (tzn. wcześniej strzał miałem przypisany bezpośrednio do broni) cały czas pojawiają się błędy. W przypadku skryptu podobnego do tego w tutorialu:
    public int zapasAmunicji = 1;

    void OnTriggerEnter(Collider other)
    {
    if (other.tag == „Player”)
    {
    Transform bron = other.transform.Find(„MainCamera/RevolverWeapon”); // tak, MainCamera mam bez spacji
    bron.SendMessage(„DodajAmunicje”, zapasAmunicji); // DodajAmunicje() kontroluje max amunicje, wiec tutaj pomijam warunek
    Destroy(gameObject);
    }
    }

    wyskakuje: SendMessage DodajAmunicje has no receiver!
    Próbowałem to również zrobić w ten sposób (tak początkowo wyglądał u mnie skrypt) i wydaje mi się, że wszystko powinno działać. Wyszukuje obiekt gracza, następnie w obiektach potomnych wyszukuje skyptu ReevolverShooting (czy źle to rozumiem):
    GameObject gracz;
    RevorverShooting strzal;
    // ilość podniesionej amunicji;
    public int zapasAmunicji = 1;
    void Start()
    {
    gracz = GameObject.FindGameObjectWithTag(„Player”);
    strzal = gracz.GetComponentInChildren();
    }
    void OnTriggerEnter(Collider other)
    {
    if (other.tag == „Player”)
    {
    strzal.DodajAmunicje(zapasAmunicji);
    Destroy(gameObject);
    }
    }

    Wyskakuj: NullReferenceException: Object reference not set to an instance of an object
    Hierarchia wygląda u mnie następująco : Player/MainCamera/RevolverWeapon (w tym ostatnim skrypt strzału) .Dodam jeszcze, że przeniesienie broni bezpośrednio jako potomka Playera nie przynosi efektów, natomiast po przypisaniu skryptu strzału bezpośrednio do gracza i zmianie GetComponentInChildren na GetComponent wszystko działa dobrze.

    • Jeżeli pojawia się błąd ” SendMessage DodajAmunicje has no receiver!”, możliwe w sumie są 2 warianty. Skrypt nie znajduje obiektu, albo nie znajduje funkcji, przy czym, raczej ma problem z tym drugim. Kod wydaje się w porządku więc posprawdzałbym w sumie nazwy – wielkość liter ma znaczenie. Istotny może być też typ zmiennej, który podajesz do SendMessage oraz publiczność funkcji. Tzn. DodajAmunicję powinien być publiczny, a do tego, jeśli oczekujesz np. zmiennej typu float, a podajesz zmienną typu int, może to być źle zinterpretowane. Na zasadzie: Szukam funkcji DodajAmunicję(int zmienna), a mam tylko DodajAmunicje(float zmienna), więc nie ma tego, czego szukam.

      W drugim przypadku, nie jestem pewny, ale wydaje mi się, że getComponentInChild sprawdza tylko na jeden poziom w dół. Tzn. jeśli obiekt gracza, ma jako childa MainCamera, a bron jest childem MainCamera, to Twój kod szuka skryptu tylko w MainCamera. Więc aby to działało, przed odwołaniem do getComponentInChild, można najpierw dostać się do childa obiektu gracza, jakim jest MainCamera.

    • Szymon Dudzik

      Podszedłem jeszcze raz do kodu i…. wszystko działa :D Naniosłem kilka poprawek i poprawiłem przejrzystość kodu, może dlatego udało mi się usunąć poprzednią nieścisłość. No i teraz zastanawiam się, czy już wcześniej przypadkiem nie przeniosłem kodu zarządzającego amunicją z broni bezpośrednio do obiektu gracza (tak jak mam to obecnie). W tedy jasne by było dlaczego „SendMessage has no receiver!”. Głupie niedopatrzenie, a potrafi zatrzymać prace w miejscu.

      Wracając do GetComponentInChild – a czy przypadkiem nie sprawdza tak długo, aż znajdzie pierwszy pasujący? Na pewno jest tak w drugim przypadku (skrypt broni odwołujący się do skryptu gracza), bo przy pomocy InParent wszystko działa bez problemu :)

      W każdym razie wielkie dzięki za odpowiedź :)

  • Pingback: Unity3d FPS Tutorial #5 - Kamera z bronią i strzelanie | mWin()

  • Ammon

    Jeżeli chciałbym zrobić drop itemów w 1 miejscu różny?
    Np. chciałbym żeby postać wchodząca do domku i idąca do kuchni, znajdzie raz w lodówce jajka a za drugim razem np napój.
    Czyli randomowy resp itemów, za każdym razem w jednym miejscu znaleźć można będzie kilka różnych itemów, tworzę SV i nie chcę żeby np w bazie wojskowej znajdowała się snajperka po którą gracz co 5minut będzie wracał bo jej resp się nie zmieni, ten spoób pozwoli raz znaleźć tam broń a raz coś innego.

    Staram się to robić z random i ID, czyli każdy item będzie miał inne ID, problemem jest stworzenie bazy danych [nie wiem jak ją zrobić i gdzie] gdzie znajdować się będą te ID.

    • Ammon

      Najlepiej jakbym to zrobił w sposób aktywacji triggerem, czyli OnTriggerEnter i tutaj kod na random resp itemów w danym colliderze, zredukuje to użycie pamięci do respu itemów na całej mapie, jest jakiś sposób na takie działanie?
      Po wejściu do miasta w którym jest 1 główny collider trigger i resp itemów potem w mniejszych colliderach?

      Czyli miasto duży collider trigger a w nim w domku dwa mniejsze triggery które aktywują się po wejściu do miasta i dadzą tam resp jakiegoś itemu

    • Na dobrą sprawę, możesz losować drop w momencie gdy gracz do niego zaglądnie, to znaczy w momencie otwarcia np. tej lodówki.
      Teraz skrypt na random, może losować przedmiot z jakiejś puli z jakimś prawdopodobieństwem.
      Czyli ustawiasz sobie 2 tablice, jedną z listą przedmiotów, drugą z prawdopodobieństwem wystąpienia. Obie publiczne, żeby dało się ustawić całość w Unity. I masz np.:
      Snajperka – 0.2
      Jajko – 0.4
      Jabłko – 0.4
      Potem losujesz sobie liczbę od 1 do 100 i: 1-20 = Snajperka, 21 – 60 = Jajko, 61-100 = Jabłko.

      Do tego skrypt musi pilnować czy skrzynka została opróżniona. Bo jeśli gracz tam zaglądnie, znajdzie dwa jabłka i snajperke, weźmie jabłko, wróci później po snajperkę żeby znaleźć trzy jajka, to będzie trochę dziwnie.

    • Ammon

      Dziękuję :)

      Chociaż rozwiązanie nad którym pracuję zajmuje trochę miejsca.
      Posługuję się OnTriggerEnter’em i

      if(ID = 1) { dodaj item1 do eq
      if (ID = 2) { dodaj item2 do eq

      I przy powiedzmy 150 itemach taki kod na same podnoszenie zajmie 450 linii jak nie mniej.

      Jest może jakiś wydajniejszy sposób?

    • Ammon

      Sorki za te męczące pytania :D

      Znalazłem sposób na problem z długim kodem, dodałem tagi jedzenia i broni i po wejściu Random value decyduje co to będzie [czy jajka czy chleb]

      Teraz chciałbym wiedzieć jak dodać graficzny wygląd przedmiotu, czyli zrobię że po wejściu do Collidera Miasto1, wszystkie małe collidery w nim wylosują co stworzą, chciałbym wiedzieć jak dodać skórkę do wylosowanego itemu, tak żeby nie było że gracz zdobędzie jabłko a na półce leży granat albo latarka

    • http://mwin.pl/unity3d-quicktip-28-prosty-inwentarz/
      Zaglądnij do tego poradnika, tam dokładniej omówiłem kwestię inwentarza.
      Druga część jest tu:
      http://mwin.pl/unity3d-quicktip-29-rozbudowany-inwentarz/
      Odpowiedzieć w komentarzu na to pytanie jest dość ciężko.

      Jeżeli chodzi o wywołanie colliderów będących wewnątrz innego, to trochę dziwne i raczej bez sensu. Lepiej jest wywoływać je na mniejszą skalę, bo po co wywołać np. 30 colliderów skrzynek, jak i tak gracz otworzy np. 2?

    • Ammon

      Też racja, ale jeżeli będzie to świat otwarty, wejdę do domu do jak aktywować tam Triggera do stworzenia przedmiotów, chyba że podczas wczytywania gry zrobić resp wszystkiego a po podniesieniu przedmiotu zrobić np 2minutowy Timer do ponownego respu tego przedmiotu

    • Ja bym to ogarnął tak:
      onTriggerEnter() {
      if(jeżeli mamy pustą zawartość boxa i minal odpowiedni czas) {
      // Generuje jakąś zawartość
      }
      }
      Trigger nałożony na np. skrzynkę, którą da się otworzyć.

      Czas sprawdzałbym tak, że zapamiętywałbym czas kiedy gracz zabrał ostatni przedmiot ze skrzyni. Teraz odejmujesz ten zapamiętany czas od obecnego i porównujesz do jakiejś tam ustalonej wartości.

      Ostatecznie: Jeżeli skrzynia jest pusta, a gracz zebrał ostatni przedmiot z niej np. 10min temu to losujesz nową zawartość, a jeśli coś jest w środku to niech sobie leży.

  • franek dolas

    witam, mam problem mianowicie wyrzuca mi błąd:

    NullReferenceException: Object reference not set to an instance of an object
    AmmoPack.OnTriggerEnter (UnityEngine.Collider other) (at Assets/Scripts/AmmoPack.cs:13)

    moja 12 i 13 linijka w AmmoPack.cs to:

    Transform gun = other.transform.Find(„Main Camera/Gun”);
    if(gun.GetComponent().canGetAmmo()) {

    widziałem w komentarzach taki sam problem ale nie bardzo zostało to rozwikłane, a i przy okazji to odnośnie przeładowania giwery zachodzi u mnie dziwna sytuacja mianowicie oddając kilka strzałów moge sobie przeładować wciskając r ale kiedy wyzeruje clipa to samo automatycznie się przeładowuje pomimo komunikatu Press R or Fire to Reload. chodzi mi o to że nie czeka na wybór R lub Fire tylko samo się przeładowuje, to tak ma być?

  • franek dolas

    Nie wiem czy zwróciłeś uwagę ale w 7 odcinku w akapicie Przygotowanie gdzie piszesz że wykorzystałeś darmowy obiekt beczki, który nam dorzucasz to nie ma żadnego linku do assetu, przynajmniej ja go nie widze

    • Ciekawe, że przez tyle czasu nikt na to nie zwrócił uwagi. :) Ale w sumie wynika to z pewnej trochę ściemy, bo nie użyłem beczki, tylko Cuba z dorzuconą na niego teksturą. Tak naprawdę, modele mają tam najmniejsze znaczenie ;)

  • franek dolas

    witam, fakt o brakującym linku to było tak poza konkursem, czy mógłbyś poradzić coś na moje wcześniejsze pytanie tzn. o błędzie:

    NullReferenceException: Object reference not set to an instance of an object
    AmmoPack.OnTriggerEnter (UnityEngine.Collider other) (at Assets/Scripts/AmmoPack.cs:13)

    moja 12 i 13 linijka w AmmoPack.cs to:

    Transform gun = other.transform.Find(„Main Camera/Gun”);
    if(gun.GetComponent().canGetAmmo()) {

    w komentarzach poniżej pojawił się już ten problem ale nie jest on do końca rozwikłany, dzięki za wszystkie odpowiedzi i przede wszystkim że szybko na nie odpowiadasz

    swoją drogą to jak dodałeś tekstury do Cube’a?

    • Błąd informuje o tym, że zadeklarowana zmienna nie ma wartości. Czyli albo Twoja zmienna gun jest pusta, czyli nie znalazło obiektu (Tutaj możesz mieć inny układ obiektów w Hierarchy, albo inne nazwy (wielkość liter ma znaczenie). Ewentualnie nie znalazło Ci komponentu, co oznaczałoby znów, że nie masz skyrput shooting dobrze przypisanego, albo znów masz go inaczej nazwanego.
      Polecam tutaj dwa tutoriale:
      http://mwin.pl/unity3d-quicktip-24-debugowanie-skryptow/
      http://mwin.pl/unity3d-quicktip-25-jak-zdebugowac-gre-w-unity3d/
      Które pomogą Ci w rozwiązaniu jakichś 90% problemów.

      Teksturę dodaje się przez:
      1) Utworzenie materiału (w oknie panel klikasz prawym i w menu Create wybierasz Material).
      2) Dodanie do materiału tekstury (z poziomu Inspektora)
      3) Przeciągnięcie materiału z okna Project na wybrany obiekt (nie ważne czy przeniesiesz na niego w oknie Scene czy Hierarchy w Unity działa każda wersja).
      Metody przypisywania tekstur były omówione we wcześniejszych częściach.

  • Iksin

    Chciałbym zapytać czemu ten kod nie działa. Po obejrzeniu 7 i 8 odcinka postanowiłem zrobić paczkę broni która dodawała by amunicje dopiero po naciśnie przycisku „E” ponieważ zanim gracz zobaczy do jakiej broni ta paczka juz ją może zebrać i poprawiłem ten kod na taki
    ale gdy podchodzę przedmiot od razu nie wyświetlając nic i nie dodają amunicji

    using UnityEngine;

    using System.Collections;

    public class AmmoPack : MonoBehaviour {

    public float ammunition = 25.0f;

    public float gunType = 1.0f;

    private Transform gun;

    private bool isPlayer;

    void OnTriggerEnter(Collider other)

    {

    if(other.tag.Equals(„Player”)) {

    gun = other.transform.Find („GameObject/Camera/M1”);

    if (gunType == 1) {

    gun = other.transform.Find („GameObject/Camera/M1”);

    }

    if (gunType == 2) {

    gun = other.transform.Find („GameObject/Camera/M4-A1”);

    }

    if (gunType == 3) {

    gun = other.transform.Find („GameObject/Camera/AK-47”);

    }

    }

    }

    void OnTriggerStay(Collider other)

    {

    if (other.tag.Equals („Player”)) {

    isPlayer = true;

    if (Input.GetKeyDown (KeyCode.E)) {

    if (gun.GetComponent ().canGetAmmo ()) {

    gun.SendMessage („addAmmo”, new Vector2 (ammunition, gunType));

    Destroy (gameObject);

    }

    }

    }

    }

    void OnTriggerExit(Collider other) {

    if(other.tag.Equals(„Player”)) {

    isPlayer = false;

    }

    }

    void OnGUI(){

    if(isPlayer) {

    GUI.Label(new Rect(Screen.width / 2 – 50, Screen.height / 2 – 10, 100, 20), „Press E to grab”);

    }

    }

    }

    • Czy mogę prosić o kod wklejony do Pastebina? W takiej formie, nie da się go w ogóle czytać.

    • Iksin
    • Obiekt znika od razu, czy nic się po prostu nie dzieje?
      Potencjalnych błędów widzę kilka:
      1) Nie znajdujesz żadnej broni i obiekt gun jest pusty. Zastanawia mnie ścieżka: „GameObject/Camera/M1”, masz obiekt GameObject w hierarchy?
      2) Gracz nie ma tagu Player
      3) Jakiś dodatkowy obiekt ma tag „Player”.

    • Iksin

      1)Ten GameObject to obiekt między graczem bez niego bron przy patrzeniu w gore lub w dol nie naturalnie sie wydluza nie wiem czym to jest spowodowane, szukałem nikt nie miał takiego problemu wymyśliłem takie rozwiązanie i działa nie wiem dlaczego ale dział
      2)Gracz ma Tag Player
      3) Nic oprócz gracza nie ma takiego Tagu
      4)Już nie wiem czy mam jakąś chorą wersje unity czy co ale teraz jeszcze gdy po odcinku 11 i 12 stworzyłem gracza wyświetla mi się błąd „Nullreferenceexception:(null) nie przeszkadza w niczym, wszystko działa a wyświetla się 7 razy w konsoli
      5)Normalne ammopack działa to już obejdę bez tej koniecznosci wcisnięcia E

  • Skydrovski

    Mam taki problem że jak ustawie tag na Player to nie mogę poruszać myszką.

    • Jak odznaczysz tag to wszystko działa normalnie? Dziwne, bo tag nie powinien mieć takiego wpływu na rozgrywkę. Szczerze, nie mam pojęcia o co chodzi i jestem zaskoczony.

    • Skydrovski

      Mogę ci podesłać mój projekt. Używam Unity 5.0.0f4

    • OK.

    • Kacper Grochowski

      pogrzeb w standard assest character firstperson character script mouse lock może tam znajdziesz rowiązanie (tak przypuszczam)

  • W tej paczce są same standardowe assety. Jeśli coś miałbym wymyślić to raczej potrzeby jest cały projekt.

    • Skydrovski

      Cały projekt waży 600 MB a w rar 200 MB. Mam za słabe łącze żeby przesyłać takie duże pliki.

    • Hmmm… nie bardzo mam inny pomysł, zwłaszcza, że błąd raczej nie powinien mieć miejsca. :/

  • Faktycznie komuś się to może przydać, więc podpiąłem. :)

  • Rafal Marchewka

    W unity 5 zamiast
    Transform gun = other.transform.Find(„Main Camera/Gun”);
    trzeba zrobić
    GameObject gun = GameObject.Find(„Main Camera/Gun”);

    To rozwiązuje błąd NullReferenceException: Object reference not set to an instance of an object