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

Temat: Przybliżenie i dziury po kulach

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 – Przybliżenie 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

W dzisiejszym odcinku, dopieścimy naszą broń i zostawimy już temat dopracowywania elementów. Co zrobimy dzisiaj? Dwa elementy, finalizujące broń. Zoom po naciśnięciu prawego klawisza myszki, oraz efekt dziur po kulach.

Do wykonania tej części, potrzeba tylko tekstury dziury po kuli. Ja używam tego:

Dziura po kuli
Dziura po kuli

Przycelowanie – zoom

Tutaj sprawa jest prosta, bo wystarczy manewrować odpowiednim elementem kamery, by uzyskać efekt przybliżenia. Ponownie operować będziemy na skrypcie Shooting.cs. Żeby nic się nie posypało zapisujemy sobie zmienne pomocnicze:

Nie są to wartości znikąd. Jeśli wjedziesz do Unity i zaznaczysz obiekt Main Camera, to w komponencie Camera znajdziesz wartość: Field Of View. Zmienna defaultFieldOfView, to wartość, która jest ustawiona domyślnie, druga wartość jest odpowiednio pomniejszona, by uzyskać efekt przybliżenia. Wartość zooma najlepiej dobrać doświadczalnie, czyli ustawiać jakieś wartości i zobaczyć, jaka najlepiej wygląda.

Teraz, przechodzimy do funkcji Update, gdzie dodajemy taki kodzik:

Przeanalizujmy linia po linii. Pierwszy if, sprawdza czy rodzin naszego obiektu (w tym wypadku broni) posiada komponent Camera. Jeżeli tak jest, zapisujemy go sobie do zmiennej cam. Następnie rozważamy dwa przypadki, gdy naciśnięty jest przycisk Fire2 (czyli prawy klawisz myszki – można to zmienić w ustawieniach Input: [Edit -> Project Settings… -> Input]). Jeżeli przycisk jest naciśnięty, chcemy przybliżyć, jeśli nie, oddalić. Robimy to odpowiednio zmniejszając lub zwiększając fieldOfView, do którego mamy łatwy dostęp dzięki zmiennej cam.

Zostaje kwestia ifów wewnątrz. Są one po to, żebyśmy mogli zmniejszać/zwiększać parametr co 1, dzięki czemu uzyskamy efekt płynnego przejścia. Tutaj swoje zastosowanie mają nasze zmienne pomocnicze, dzięki którym nie przekroczymy ustalonych wartości.

Tyle! Zoom działa!

Dziury po kulach

Póki jesteśmy w skrypcie, możemy najpierw dodać kod. Znów zaczynamy od zmiennej pomocniczej:

Będzie to prefabrykant naszej dziury. Teraz samo pojawienie dziury, dodajemy go w warunku trafienia w ścianę po strzale:

Tworzymy sobie obiekt, dzięki znanej nam funkcji instantinate. Ciekawe jest tutaj jedynie użycie hit.point i hit.normal do określenia rotacji i położenia dziury. Dzięki temu, dziura pojawi się tam, gdzie padł promień strzału broni, oraz zawsze będzie ustawiona wektorem Y prostopadle do powierzchni. Daje nam to tyle, że dziura nie pojawi się na ścianie np. bokiem. W sumie tyle kodu, czas przygotować dziurę. Wracamy do Unity.

Schemat jest prosty. Tworzymy sobie Cube: [GameObject -> 3D Object -> Cube] – mój się nazywa Hole.  Spłaszczamy go, ustawiając Scale.y na 0. Nakładamy teraz na niego teksturę dziury. Zmieniamy jeszcze Shader na Transparent/Bumped Diffuse, dzięki temu dziura będzie miała przeźroczyste tło, jeśli takowe będzie posiadał plik.

Poprawny obiekt Hole
Poprawny obiekt Hole

Teraz tworzymy pusty GameObject [GameObject -> Create Empty] – mój się nazywa BulletHole. Obiekt Hole ustawiamy jako child pustego gameObjectu. Ostatni krok, to ustawienie, dla obiektu Hole wartości transform position y na 0.1. Dzięki temu manewrowi, dziura zawsze będzie na wierzchu.

Zostało już tylko zrobić z obiektu BulletHole prefabrykant (przenosimy go do panelu Project), a następnie dodać ten prefabrykant do odpowiedniego pola w obiektach broni (te przygotowane wcześniej publiczne pola).

Jeżeli po pojawieniu się, rozmiar dziury jest za duży, wystarczy zmniejszyć parametr Scale dla komponentu Transform, naszego prefabrykantu.

Podsumowanie

Dziś nie zrobiliśmy wiele, ale dzięki temu gra uzyskała nieco uroku. Tak jak wspominałem, dalej nie będziemy się już bawić za bardzo tym co mamy, a zrobimy coś nowego.

Z racji, że w skrypcie Shooting.cs mieszaliśmy już bardzo dużo, udostępniam pełny skrypt:

 

Poprzednia część <- #9 – Rzut granatem i seria z karabinu

Następna część-> #11 – Przeciwnik z prostym AI, sztuczna inteligencja

  • Maciej

    Mam problem z tymi dziurami, dopiero jak podejdę pod samego cube’a w którego strzelam, to się na nim pojawiają dziury, ale po wielu strzałach i w całkowicie losowych miejscach z tego co widzę.

    • Wynikać może z dwóch rzeczy.
      1) Możesz mieć ustawiony dystans na dość niski.
      2) Promień strzału może być ustawiony w dziwną stronę.
      Aby rozwiązać problem dodaj sobie linijkę z funkcję Debug.DrawRay:
      https://docs.unity3d.com/ScriptReference/Debug.DrawRay.html
      Gdy odpalisz grę w okienku Scene będziesz widział jak pada linia strzału. Będzie od razu wiadomo w czym jest błąd. :)

    • Maciej

      Faktycznie, linia strzału jest wręcz prostopadła do linii, która powinna być. Co z tym zrobić, skoro kod skryptu mam z poradnika i nic nie zmieniałem?

    • Kopiowales fragmentami czy masz ten koncowy? Jak fragmentami to mozesz sprobowac koncowy.
      Jesli koncowy to moze byc zla hierarchia obiektow albo skrypt zle przypisany. Skrypt powinien byc dodany do broni, a sama bron byc childem kamery wewnatrz First Person Controllera.
      Jezeli uzywasz kontrolera z Unity 5, moze tam byc inaczej i wtedy jest to nieznany mi blad ktory musze sprawdzic.

    • Maciej

      Kopiowałem fragmentami, bo nie implementowałem wszystkiego, ale tak jak napisałem wyżej, działa po przestawieniu skryptu bezpośrednio na kamerę. Po prostu z tego co widzę to skrypt korzysta z „przodu” obiektu do którego jest przypisany a że model pistoletu w pozycji default’owej jest nieodpowiednio ustawiony to po rotacji wychodzą takie kwiatki. Chyba, że jest jakiś sposób by zmienić ten przód obiektu?
      Korzysta z ostatniej wersji Unity 3.x.x

    • w kompletnym skrypcie jest zmienna fwd. Poniera ona przod komponentu kamery. I wtedy wszystko dziala.

    • Maciej

      Dobra, już wiem w czym tkwi problem, skrypt strzelania, był przypisany do broni, która swój przód ma gdzie indziej niż kamera/postać. Przypisałem skrypt do głównej kamery i jest dobrze. Dzięki ;)

  • Vindict

    Mój promień strzału idzie co prawda do przodu jak trzeba ale jest przesunięty w dół (zaczyna się niżej niż kamera) przez co strzały zawsze trafiają za nisko. Wszystko mam jak w poradniku

    • Jeżeli wszystko jest w zgodzie z poradnikiem, to promień powinien być rzucany bezpośrednio z kamery (zmienna tf, to pobranie lokalizacji rodzica broni, którym powinien być obiekt Main Camera). Czyli rzucany promień powinien być niezależny od broni.
      Hierarchia powinna wyglądać tak:
      – FPC
      – Main Camera
      – Bron1 <- ze skryptem
      – Bron2 <- ze skryptem

      Jeżeli skrypt jest np. w childzie obiektu broni, wtedy lokacja może się przesuwać. Ogólnie: Bezpośrednim rodzicem obiektu ze skryptem musi być obiekt Main Camera, w przeciwnym wypadku, skrypt nie zadziała poprawnie.

    • Vindict

      Heh jak zwykle po godzinie szukania mam błąd. Nie zauważyłem, że zamiast „tf.transform.position” w strzelaniu miałem „transform.position” XDD Oczywiście teraz wszystko działa jak trzeba

  • Barti

    Dzięki temu Efektowi Zoom stworzyłem efekt lornetki tylko musiałem dodać włączanie/wyłączanie textury lornetki (czyli czrnego tła z dwiema dziurami obok siebie :D) którą stworzyłem w Gimpie xD (I najlepiej zmienić wartość w private float zoomFieldOfView = 40.0f; na mniejszą ;) )

  • Pingback: Unity3d FPS Tutorial #13 - Menu główne gry. GUI | mWin()

  • Skydrovski

    Da się zrobić tak żeby broń podążała za ruchem myszki jak w innych grach ???

    • Skydrovski

      Dobra poradziłem już sobie.