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

Temat: Menu główne gry. GUI

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 – Proste AI przeciwnika

#12 – Animacja postaci przeciwnika, Animator

#13 – Menu główne gry. GUI

#14 – Ostatnie szlify i budujemy projekt

Teoria

Nasz gra już nabrała kształtu. Mamy piękną wyspę, system strzelania, animowanego wroga, który „myśli”. Możemy zbierać przedmioty, mamy życie, pancerz, wytrzymałość. Finiszujemy! Dlatego dzisiaj zajmiemy się może mniej ciekawym, ale za to istotnym i często występującym aspektem gier. Jest nim oczywiście interfejs użytkownika, zwany z angielskiego GUI (Graphical User Interface).

Zrobić menu można na kilka sposobów. Albo wrzucając klikalne tekstury, albo operując na obiektach klasy GUI z Unity3d. Jak  można wnioskować po linkach, tematem już się zajmowałem, dlatego tutaj prawdopodobnie wyświetlimy tylko Logo gry z dodatkowym prostym, przyciskowym menu opartym na funkcjach GUI, dlatego, że niedawno to GUI było trochę modyfikowane przez zespół Unity.

Przy okazji poruszymy kwestię zmiany scen, oraz wyjścia z aplikacji.

Tworzymy nową scenę

Nową scenę możemy stworzyć wybierając w menu: [File -> New Scene]. Albo skorzystać ze skrótu klawiaturowego CTRL + N. Nową scenę od razu zapisujemy korzystając ze skrótu CTRL + S. Ja nową scenę nazwałem Menu.

Teraz kopiujemy sobie kilka elementów. Directional Light, Wodę i Teren. Zaznaczamy je w panelu Hierarchy na scenie gry, przechodzimy na scenę menu i wklejamy. (Nie tłumaczę jak to zrobić, bo robi się to tak samo jak w każdym systemie operacyjnym).

Teraz zostaje tylko dostosować kamerę. Dodajemy jej skybox [Component -> Rendering -> Skybox]. Wybieramy jeden z zaimportowanych do projektu Skyboxów, może być ten sam co do sceny gry, ale nie musi. Teraz ustawiamy kamerę główną, tak by by spoglądała z wysoka na wyspę. U mnie efekt końcowy wygląda mniej więcej tak:

Tutorial_13_01
Efekt ustawienia kamery w scenie Menu

 

Taka scena, będzie tłem dla naszego menu.

Dodajemy logo gry

Tworzymy sobie na początek skrypt, u mnie: Menu.cs. Dodajemy skrypt do kamery głównej i wchodzimy w edycję skryptu. Na start dodajemy sobie tylko jedną zmienną:

Oczywiście, będzie to tekstura naszego logo. Jednak zanim ją dodamy, napiszemy skrypt, który ją wyświetli:

Funkcja OnGUI odpowiada za wyświetlanie elementów interfejsu. Jest ona wywoływana przy każdym evencie (zdarzeniu) interfejsu, co sprawia, że może być wywołana nawet kilka razy w trakcie jednej klatki.

Sama funkcja DrawTexture, odpowiada za… narysowanie tekstur. Pierwszy parametr to obiekt typu Rect – czyli zwykły prostokąt, gdzie podajemy jego położenie w układzie X, Y. Oraz wymiary: Szerokość, wysokość. Drugi parametr to tekstura, którą mamy narysować.

Na wszelki wypadek podaje swoją teksturę:

Tekstura loga
Tekstura loga

Dodajemy menu

Na początek przydadzą się dwie zmienne:

Tworzymy je publiczne, żeby wymiar przycisków, dało się w prosty sposób zmienić z poziomu Unity. Dodatkowy margin, to margines, który wykorzystamy do przesunięcia przycisków by nie wyświetlały się bezpośrednio na sobie.

Teraz sam kod, oczywiście wewnątrz funkcji OnGUI:

Pierwsze co się rzuca w oczy to fakt, że przyciski wrzuciliśmy do ifów. Dzięki temu, wewnątrz ifa możemy określić co się ma wydarzyć, gdy przycisk zostanie naciśnięty. Sama budowa przycisku jest bardzo standardowa (jeśli chodzi o budowę elementów GUI). Czyli najpierw obiekt Rect ustalający pozycję, a potem treść przycisku. (Może być też obrazek, zamiast tekstu).

Druga być może nietypowa rzecz, do dodawanie dziwnych wartości do pozycji Y naszego przycisku. Gdybyśmy tego nie zrobili, przyciski pojawiły by się na sobie. A magiczne liczby to wysokość poprzedniego przycisku plus jakiś tam wymyślony przeze mnie odstęp, aby przyciski nie przylegały do siebie.

Już teraz, efekt powinien być następujący:

Menu po poprawkach
Menu po poprawkach

Teraz dodamy sobie kilka funkcji, tak aby przyciski nie były bezużyteczne:

Pierwsza linia to funkcja LoadLeve, uruchamia ona podaną jako parametr scenę. Przyjmuje ona wartość tekstową (nazwę sceny), albo liczbową (indeks sceny). Drugi typ przejścia opiszemy sobie w kolejnej części, przy omawianiu builda. Jeśli jednak bardzo Cię to interesuje, możesz poczytać o tym dokładniej w innym poradniku.

Druga funkcja pozwala wyłączyć grę. Niestety nie zobaczymy jej działania, bo funkcja nie działa w edytorze Unity3d oraz w przeglądarce.

Poprawny wygląd

Menu już mamy. Nawet coś ono robi. Ale nie wygląda fajnie. Dlatego postaramy się je nieco podrasować. Wykorzystujemy w tym celu obiekty GUI Skin. Jego wykorzystanie jest banalne. Dodajemy sobie zmienną pomocniczą:

Od razu ją też wykorzystamy. Wystarczy w funkcji OnGUI dodać:

Kod ten oznacza mniej więcej tyle, że cały układ GUI będzie korzystał z podanej w zmiennej skórki. Teraz czas ją dodać. Przechodzimy do Unity. Klikamy w oknie Project prawym klawiszem myszy na wolnym obszarze, a potem wybieramy Create -> GUI Skin (Przedostatnia pozycja). Skórkę nazywamy sobie jakoś i przypisujemy do skryptu. Skóra już teraz będzie działała, ale jej domyślne wartości pokrywają się z tym co mamy, więc nie zobaczymy efektów, jak sami czegoś nie zmienimy.

Ja u siebie usunąłem tło spod przycisków i ustawiłem czcionkę na Ariala rozmiar 50. Oraz ustawiłem inny kolor tekstu zależnie od stanu przycisku. Wyróżniamy główne 3 stany: Noraml – czyli stan spoczynkowy, domyślny. Hover – czyli gdy kursor znajduje się na przycisku. Active – czyli gdy przycisk jest aktywny, co dosłownie oznacza moment kliknięcia. Warto tutaj zauważyć, że jeśli przyciski nie posiadają tekstury tła, to zmiana koloru też nie nastąpi. Więc w przypadku gdy ja chciałem się całkowicie pozbyć tła spod przycisków, musiałem wstawić tam przeźroczystą teksturę. Opcję mojego GUI Skin wyglądają następująco:

Ustawienia GUI Skin
Ustawienia GUI Skin

Jak widać, skórka może określić masę innych elementów. Jednak opisanie każdego  z nich mija się z celem. Tutaj najlepszą nauką będzie pobawienie się tym komponentem w wolnej chwili. Już wiesz jak on działa, więc nie powinieneś mieć problemu z wykorzystaniem go do swoich potrzeb.

GUISkin vs GUIStyle

W Unity występują obie formy, ale właściwie czym się różnią? Otóż GUISkin jest zbiorem różnych GUIStyle. GUIStyle możemy przypisać bezpośrednio do konkretnego obiektu GUI. Np. przycisku. Wykorzystamy to, by wyszarzyć przycisk opcji, sugerując, że nie jest aktywny. W tym celu, dodajemy sobie zmienną pomocniczą:

Oraz delikatnie modyfikujemy kod przycisku:

Dodaliśmy jedynie trzeci parametr. Teraz gdy wrócisz do Unity i zaznaczysz w panelu Hierarchy obiekt Main Camera w panelu Inspector powinno ukazać się coś takiego:

GUIStyle w panelu Inspector
GUIStyle w panelu Inspector

Jak widać, możesz sobie z panelu bezpośrednio zmodyfikować styl konkretnego przycisku.

Grupowanie

Istnieje jeszcze jedna przydatna rzecz, o której nie wspomniałem. Mianowicie grupowanie obiektów GUI. Najpierw to zrobimy, a potem wyjaśnię do czego to się może przydać. A kod modyfikujemy jedynie tak:

Dodaliśmy dwie istotne funkcję. Oczywiście BeginGroup oznacza otwarcie grupy, a EndGroup jej zakończenie. Zmieniliśmy też położenie w osi X i Y przycisków na 0, 0. Dlaczego? Ponieważ teraz położenie grupy, przejęło na siebie ustawienie całości, a przyciski ustawiamy względem początku grupy.

Brzmi zawile. Dlatego wyobraź sobie grupę jako pudełko. Przyciski ustawiamy w pudełku w jakimś tam układzie. I teraz bez względu na to, gdzie przeniesiemy pudełko, przyciski w nim będą zawsze ustawione tak samo.

Responsywność

Na koniec została jedna, często pomijana rzecz. Responsywność. Jest to nic innego jak dostosowanie rozmiaru GUI do rozdzielczości ekranu. Po co to? Gdy ustawimy szerokość przycisku na 400px, w rozdzielczości 1920×1080, będzie wyglądał fajnie. Ale gdy ktoś zagra w naszą grę przy rozdzielczości 800×600 przycisk zajmie połowę szerokości ekranu!

Robimy to wykorzystując prostą proporcję. Najpierw musimy założyć sobie nasza natywną rozdzielczość, czyli tą, pod którą dedykujemy grę. Ja u siebie zakładam fullHD, czyli 1920×1080. Dlatego dokładam taki kod:

Jak wspominałem, bardzo prosta proporcja, gdzie szerokość/wysokość przycisku, mnożymy przez aktualną wysokość/szerokość ekranu i dzielimy przez natywną. Tym sposobem otrzymujemy rozmiar przycisku dla odpowiedniej rozdzielczości.

Oczywiście to samo wypada zrobić z położeniami na osi X i Y różnych obiektów. Jednak to, zostawiam jako Twoje zadanie domowe, aby nie rozciągać tej i tak już długiej części.

Podsumowanie

Dzisiaj poznaliśmy podstawowe zagadnienia związane z obsługą GUI. Poznaliśmy opcję grupowania, obsługę przycisków, czy rysowanie tekstur. Oczywiście Unity oferuje znacznie więcej kontrolek i opcji, jednak do stworzenia typowego menu gry, nie potrzebujemy nic więcej.

 

Poprzednia część <- #12 – Animacja postaci przeciwnika, Animator

Następna część -> #14 – Ostatnie szlify i budujemy projekt

  • I poruszysz ten temat jescze nie raz a kiedy seria o androidzie

    • Pewnie tak.
      Na pewno nie przed zamknięciem tej. No i pewnie zrobić sobie parę dni wolnego od tutoriali. I na kurs poczekam do Unity 5.0. Sam Android tak naprawdę zmienia tylko system sterowania, więc mogę się pokusić na QuickTipa o sterowaniu na Androidzie, jeśli Ci to pomoże. ;)

    • Dzięki ale zrób jeszcze drzewko umiejętności do tej serii i że po 10 seoundach celowania( o ile było celowanie xD) ono się wylancza a ją podstawie tego zrobię resztę drzewka

  • Dawid Lewandowski

    zrobisz jak zrobić animację strzału broni?

    • Raczej wątpię, ale mogę to jeszcze przemyśleć. Najbliższą część planuje na pon i miał być ostatnim odcinkiem, ale zobaczę jeszcze. ;)

  • BOOMBOOX

    Mam trochę głupie pytanie ale robiąc ekran startowy (Nadawanie imienia ,dodawanie atrybutów) chciałem dodać tło dla przycisków oraz linijek które wyświetlają napisy. Ale po dodaniu grafiki(GUISkin) napisy znikają zostaje sama grafika po usunięciu jej nie ma śladu po napisach

    • Jeżeli jesteś w stanie do mnie napisać maila z jakimiś screenami tego co się dzieje wraz z ustawieniami, to będę wdzięczny. Z tego opisu nie bardzo jestem w stanie zrozumieć problem.

  • Mam pytanie, zadaję tutaj bo nie wiem za bardzo gdzie. W mojej gdzie chciałem wykorzystać funkcję OnMouseEnter. Sprawdziłem działa, ale przestaje, gdy ukrywam kursor. Działa jednak przy zablokowaniu kursora myszy (Screen.lockCursor), kursor jednak blokuje się na swojej poprzedniej pozycji. Czy jest możliwość przesunięcia go? Jedyna jaką znalazłem kosztowała 15 dolarów :/. Ewentualnie inna funkcja o podobnym działaniu ale żeby oddziaływała na środek ekranu?

    • Funkcja Screen.lockCursor powinna ukryć i zablokować kursor na środku ekranu. I w sumie jest to jedyna opcja.
      Możesz np. ustawić pozycję kursora na środku ekranu (co wymaga odpowiednich bibliotek i nie zawsze zatrybi, ustawiając własną teksturę kursora jako przeźroczystą teksturę.

  • Arek Lewandowski

    Witaj czy nie mógł byś dodać linka do pełnego projektu ?
    Robie wszystko tak jak jest w każdej części poradnika lecz nie przeciwnik nic nie robi nie ma dźwięku strzału broni itp. żadne błędy nie wyskakują a tego najważniejszego nie ma :/

    • Jutro wrzucę część 14, z kilkoma poprawkami i wtedy dorzucę co najmniej wszystkie skrypty. Kompletny projekt dam do pobrania na sam koniec, czyli w części 15. Nie chce po prostu wrzucać całego projektu w połowie produkcji.

      Wykonywane dokładnie tutoriale powinny poprowadzić do poprawnego rozwiązania. Co może powodować błąd?
      Animacja:
      – Brak Collidera dla przeciwnika – lub zły typ, albo zbyt mały rozmiar
      – Błędy (nie składniowe) w skrypcie. Czyli np. jakaś funkcja umieszczona w złym miejscu
      – Brak animacji dla przeciwnika (przy użyciu innego modelu niż podany przeze mnie)
      Dźwięk:
      – Brak komponentu AudioSource
      – Wywołanie dźwięku w złym miejscu w skrypcie
      – Nie przypisanie klipu dźwiękowego do zmiennej

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

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

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

  • Ezioleq

    W moje urodziny :D

  • Franek Barszcz

    Mógłbyś dawać na końcu każdego poradnika pełny skrypt żebym mógł błędy sprawdzić

    • Czasem dodaje, kiedy było dużo zmian w napisanym wcześniej pliku. Jednak najczęściej ich nie dodaje, bo wtedy sporo osób kopiuje tylko gotowca i nie czyta tekstu, po czym są zdziwieni, że nie działa (bo pominęli masę kroków, po za skryptowych). Kiedy dodaje na końcu pełny skrypt najczęściej dostaje dużo więcej pytań i wątpliwości, niż jak skryptu nie ma. Jeżeli gdzieś masz problem z działaniem, daj znać. Postaram się pomóc ;)

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

  • frandzelek

    Czy wszystkie skrypty mam dawać do jednego plikowego skryptu?

    • Jeżeli chodzi o ten fragment kodu, to tak. Jeżeli trzeba przejść do innego pliku to wspominam o tym. :)

  • kacper lubkowski

    wczoraj zainstalowałem unity i nic nie ogarniam pomógłbyś?

    • Proponuję przerabiać ten poradnik od samego początku, krok po kroku dokładnie czytając instrukcję. Jeżeli będziesz miał jakieś pytania to dawaj znać.
      Samo pytanie jest na tyle ogólnikowe, że w sumie nie wiem czego oczekujesz.

    • kacper lubkowski

      umiem robić kolizje i animacje ale nie znam się na skryptach i robie grę 2D

    • To tak jak mówiłem. Jeżeli chodzi o skrypty, to polecam przerobić tutorial (może też kurs C#, który obecnie produkuję), a potem tworzyć. W razie trafienia na jakieś konkretne problemy, możesz do mnie pisać na FB, czy przez maila – jak będę w stanie, to pomogę ;)

    • kacper lubkowski

      na fb napisałem już

  • Amelia

    Czy przyciski powinny dodać mi się same czy muszę je utworzyć?

    • Jeżeli dodasz kod z poradnika, to przyciski powinny się utworzyć.

  • TetraHydroSoft

    halo nie wiem co jest level nie chce mi się załadować mimot to że błędów niewywyala i zmieniłem nazwe z „game” na swoją czyli „Level 1”

    • Pokaż 3 rzeczy:
      1) Kod (przez pastebin)
      2) Okienko Hierarchy ze scenami
      3) Okienko build: [File -> Build Settings]

    • Marcin

      Ooo dzieki że mi podpowiedziałeś z tą hierarchią :D już działa :D wystarczyło że Level 1 przeniosłem w okno hierarchy i zrobiłem Unload scene :D tylko właściwie takie pytanie jak klikam przycisk graj to włącza mi się ten nowy level ale tło gry mam bardzo przyciemnione czy w normalnej grze też tak będe miał wiesz chodzi mi o to że unity wykonuje przez ten czas te swoje 11 zadań i aby grafika była rozjaśniona trzeba poczekać

    • Unity wtedy renderuje całą grę w locie. Potem zrobi to w trakcie robienie builda i gra powinna śmigać. Najlepiej zrobić sobie testowego builda i sprawdzić. ;)

    • Marcin

      aaa i przy okazji jeśli to czytasz to mam problem z animacjami ponieważ zmieniałem nieco twój kod i dodałem animacje do przeładowania jak i do strzału ale animacja przeładowywania nie wyświetla mi się do końca prawidłowa animacja powinna wyglądać w ten sposób że broń unosi mi się do góry wypada magazynek następnie magazynek wraca zamek mi się przeciąga i broń wraca do swojej pozycji natomiast wyświetla mi się w ten sposób że tylko w tej animacji zamek mi się przeciąga i wraca na swoją pozycje P.S podaj mi do siebie E-mail to ci podeśle Filmik jak to wygląda bo na tej stronie się raczej filmiku nie da wstawić prawda?

  • Agentbarti

    Czy możesz zrobić jak zrobić menu gry czyli naprzykład gra się w gre i klika się escape i wyskakuje menu gry bo ja tak zrobiłem i wtedy nie pokazuje się kursor myszy

    • W trakcie kursu ukrywamy kursor myszy. Musisz po prostu znaleźć linijkę która to robi i po włączeniu menu „pojawić” kursor.

    • Agentbarti

      Nie bo ja nie zrobiłem ukrytego kursora myszy. Więc może ty byś na to poradził bo ja
      na razie się zbytnio nie orientuje w UNITY.