Unity3d QuickTip – czyli szybkie porady, rozwiązania częstych problemów i sztuczki w Unity3d!

Dzisiejszy odcinek: Jak zrobić skalowalne menu

Uwaga! Jest to poradnik typu QuickTip. Zatem skupia się on na osiągnięciu założonego celu. Zatem zakładamy że użytkownik zna na tyle program Unity3d, aby samodzielnie wykonać najprostsze czynności, jak np. dodanie modelu kostki do sceny czy dodanie modelowi jakiegoś komponentu. Jeżeli brakuje Ci tej podstawowej wiedzy, zapraszam do tutoriala:
Unity Tutorial – Podstawy

Ten tutorial opisuje jak zrobić menu za pomocą GUI. Jeżeli interesuje Cię menu zrobione za pomocą tekstur, zaglądnij tutaj.

Teoria

Menu to sprawa oczywista. W każdej grze, na samym początku trafiamy na wybór: Nowa gra, wczytaj grę, opcję, wyjdź z gry. Wnioskuję więc, że sensu tworzenia tego typu komponentu nie muszę tłumaczyć.

Ogólnie mamy dwie możliwości stworzenia menu. Używając GUITexture, oraz używając klasy GUI i kompozycji graficznej. Pierwszy sposób, zapewnia nam ładny efekt, w dość prosty sposób. Jednak druga metoda, jest bardziej uniwersalna, bo możemy łatwo dostosować wygląd menu do rozdzielczości ekranu, co może być bardzo przydatne, przy tworzeniu gier na urządzenia mobilne.

W tym QuickTipie omówię jedynie tworzenie menu skalowalnego. Menu na podstawie GUITexture poświęcę oddzielnego QuickTipa.

Przygotowanie

Żeby stworzyć menu, potrzebujemy oczywiście nową scenę. Jednak w niej wystarczy nam kamera oraz skrypt, który do kamery przypiszemy. To co widać w tle kamery będzie tłem menu. Więc tutaj zostawiam waszej wyobraźni, co można tam umieścić. Począwszy od jakiejś tekstury, przez skyboxa, do po prostu kawałka gry (można skopiować jakąś gotową scenę, umieścić kamerę w ciekawym miejscu i na takim tle, budować nasze menu).

U siebie, pozostawiłem całość na wartościach domyślnych, więc menu powstanie na jednolitym tle.

Tworzymy menu

Najpierw, musimy sobie przygotować zmienne, gdzie będziemy trzymać nasze przyciski, oraz wspomnianą kompozycję graficzną (GUISkin). Typ Rect, którego użyjemy, jest typem prostokąta. Posiada swoją długość, szerokość i położenie. Stosuje się go najczęściej do ustawienia pozycji danego elementu.

public GUISkin menuSkin;
public Rect menuArea;
public Rect playButton;
public Rect scoresButton;
public Rect quitButton;

Następnym krokiem będzie przypisanie do naszego GUI, kompozycji graficznej. W tym celu należy utworzyć funkcję, która odpowiada za kreowanie GUI, czyli: onGUI();

void OnGUI() 
{
	GUI.skin = menuSkin;
}

GUI jest ogólną klasą, która zawiera w sobie wszystkie ustawienia naszego interfejsu użytkownika. Parametr skin, odpowiada za to, z jakiej kompozycji korzystamy. Jest to łatwy sposób, do szybkiej zmiany wyglądu menu.

Następnym krokiem, będzie utworzenie naszych przycisków, oraz zaprogramowanie im funkcjonalności. W tym celu tworzymy następującą konstrukcję:

GUI.BeginGroup(menuArea);
	if(GUI.Button(new Rect(playButton), "Play")) {

	}
	if(GUI.Button(new Rect(scoreButton), "Score")) {
			
	}
	if(GUI.Button(new Rect(quitButton), "Quit")) {
				
	}
GUI.EndGroup();

Całość umieszczamy wewnątrz funkcji onGUI. Ale co właściwie zrobiliśmy? BeginGroup i EndGroup określają nam grupę obiektów. Jako parametr podaliśmy nasze menuArea, które jest typu Rect. Najprościej mówiąc określi on nam, gdzie ma się znaleźć menu.

Polecenie GUI.Button tworzy nam przycisk. Jego dwa parametry to rozmiar, typu Rect, oraz nazwa, która wyświetli się na przycisku.

Wprowadzenie tworzenia przycisku, wewnątrz funkcji warunkowej if, sprawia, że to co znajduje się wewnątrz instrukcji, wykona się jedynie po kliknięciu przycisku.

Dodajmy sobie teraz, funkcjonalności:

if(GUI.Button(new Rect(playButton), "Play")) {
	Application.LoadLevel("Level1");	
}

if(GUI.Button(new Rect(scoreButton), "Score")) {
	Application.LoadLevel("Scores");	
}
			
if(GUI.Button(new Rect(quitButton), "Quit")) {
	Application.Quit();
	Debug.Log ("Have Quit");
}

W przypadku poziomów, jedynie ładujemy nowy poziom, za pomocą funkcji LoadLevel. Czyli lista wyników, oraz poziom gry, będzie tylko kolejną sceną.

Jeśli chodzi o wyjście z gry, służy do tego funkcja Application.Quit(); Jednak nie zadziała ona, ani w wersji przeglądarkowej, ani w czasie testów wewnątrz Unity. Dlatego dodałem wypisanie na konsoli informacji o tym, że opuszczamy grę.

Jednak, skoro wersja przeglądarkowa, nie obsługuje wyjścia, bo aby skończyć grę, przechodzimy na inną podstronę lub zamykamy zakładkę, to po co nam w takich przypadkach przycisk wyjścia?

if(Application.platform != RuntimePlatform.OSXWebPlayer && Application.platform != RuntimePlatform.WindowsWebPlayer) {
	if(GUI.Button(new Rect(quitButton), "Quit")) {
		Application.Quit();
		Debug.Log("Have Quit");
	}
}

Dodanie tej instrukcji warunkowej, sprawdza czy nasza gra uruchomiona jest w przeglądarce. Musimy sprawdzić platformę dla OSX i Windows. Unity Web Player nie działa pod Linuxem, dlatego jego nie musimy, a wręcz nie możemy sprawdzić czy przypadkiem gra nie jest uruchomiona na tej platformie.

Czas ustawić nasze przyciski w odpowiednich miejscach. Wracamy więc do Unity i zaznaczamy naszą kamerę. Gdzie jeśli dodaliśmy już do niej nasz skrypt, w panelu Inspektor, powinniśmy zobaczyć coś takiego:

Ustawienia pozycji elementów naszego menu
Ustawienia pozycji elementów naszego menu

Tak jak wspominałem, nasze zmienne typu Rect, to prostokąty. Więc posiadają: Szerokość (W – Width), Wysokość (H – Height), oraz położenie (X i Y – chodzi oczywiście o lokalizację lewego, górnego rogu).

Czas na ustawienie parametrów. Każdemu z przycisków, ustawiam szerokość i wysokość odpowiednio na: 150 i 30. Zmienna X każdego z przycisków będzie wynosić za to 0. Ponieważ będą one wewnątrz naszego placeHoldera menuArea, więc ich położenie ustawiamy względem niego. Natomiast zmienna Y, będzie ustawiona dla pierwszego przycisku na 0, a dla każdego kolejnego, będzie wynosić 40 więcej. (Wysokość przycisku to 30, a chcemy małe przerwy między nimi).

Nasze MenuArea ustawimy za to na współrzędnych 100, 100. Oraz ustawimy szerokość na 150, a wysokość na 120. Co oczywiście jest odzwierciedleniem rozmiarów przycisków. Ostatecznie otrzymałem coś takiego:

Ustawienia pozycji przycisków
Ustawienia pozycji przycisków

Teraz możesz uruchomić grę i zobaczyć jak wygląda Twoje menu. Jednak ma ono pewną wadę. Jeśli zostanie uruchomione, na różnych rozdzielczościach, będzie nieco przestawione i nie do końca tam gdzie byśmy chcieli. Dlatego potrzebujemy znormalizować nasze parametry.

Położenie, niezależne od rozdzielczości

Normalizacja, to proces, w którym nasza zmienna jest sprowadzona do zakresu od 0 do 1. Aby wykonać normalizację musimy najpierw dodać sobie zmienną.

Rect normalizedMenuArea;

Na chwile przeskoczmy do Unity i zajmijmy się parametrami menuArea. Chcemy by były znormalizowane, czyli współrzędne X i Y muszą mieścić się w przedziale 0 do 1. Można uznać to za procent w jakim mają znaleźć się od lewej, górnej krawędzi ekranu. Ja ustawiłem 0,2 – 20%.

Teraz wewnątrz funkcji Start, dobierzemy jej odpowiednie wartości:

void Start()
{
	normalizedMenuArea = new Rect(menuArea.x * Screen.width - (menuArea.width * 0.5f),
		menuArea.y * Screen.height - (menuArea.height * 0.5f),
		menuArea.width, menuArea.height);	
}

Wysokość i szerokość obiektu zostaje bez zmian. Ale operujemy na współrzędnych. Najpierw ustaloną wartość mnożymy przez szerokość/wysokość ekranu. Sprawia to, że nie ważne czy szerokość ekranu to 1024 czy 1680, 20% ekranu, zawsze wyniesie tyle samo. Później odejmujemy połowę szerokości komponentu. Robimy tak, ponieważ dzięki temu, nasz obiekt będzie wyśrodkowywany względem pozycji. Tzn. zmienne X i Y wskazują teraz jak by na środek komponentu, a nie na jego lewą górną krawędź.

Zostaje nam tylko podmienić wykorzystywany kontener:

GUI.BeginGroup(normalizedMenuArea);

I w tej chwili, posiadamy funkcjonujące menu.

Kompozycja Graficzna – GUISkin

Zaczynamy od utworzenia obiektu GUISkin. Np. kliknij prawym w panelu Project po czym wybierz: Create -> GUI Skin. Ja utworzony GUISkin nazwałem mySkin. Następnie wybierz kamerę i w parametr naszego skryptu nazwany MenuSkin, przeciągnij utworzony obiekt.

Teraz czas stworzyć wygląd. Po zaznaczeniu obiektu GUISkin, w panelu Inspektor wyświetli się masa różnych nazw kontrolek. Są to obiekty GUI jakie mogą się pojawić. My posiadamy tylko Buttony, więc nimi się zajmiemy. Kliknij na strzałkę obok napisu Button, by zobaczyć jak wiele parametrów menu, może zostać zmienione.

QuickTip_08_03
Parametry GUISkin dla przycisków

Ja ustawiłem tylko font na arial, oraz zwiększyłem rozmiar czcionki. Aby zmienić tło, potrzebna jest tekstura 2D.  Określenia Normal, Hover, Focus i Active oznaczają stany przycisku.

  • Normal, to sytuacja kiedy przycisk po prostu sobie jest.
  • Hover – kiedy został najechany myszką.
  • Focus – Zyskał “skupienie”, dla np. pola tekstowego, jest to sytuacja gdy kursor znajduje się wewnątrz pola i możemy w nim pisać. Dla buttona, będzie to sytuacja, gdy zaznaczyliśmy go za pomocą klawiatury, np. tabulatorem.
  • Active – sytuacja gdy przycisk został kliknięty, dokładnie moment kliknięcia.

Inne parametry to:

  • Border – Ramka przycisku
  • Margin – Marginesy, czyli na ile dany element, ma być oddalony od otaczających go elementów
  • Padding – Podobny do margin, ale jego rozmiar zalicza się do rozmiaru przycisku. Oznacza jak bardzo wewnętrzny tekst ma być oddalony od ramki przycisku.
  • Font – krój czcionki
  • Font size – rozmiar czcionki
  • Font style – Styl czcionki – pogrubienie, podkreślenie, kursywa
  • Aligment – Pozycja tekstu
  • Word Warp – Zawijanie tekstu

Oczywiście, tutaj najlepszym rozwiązaniem jest, pobawienie się parametrami, żeby zobaczyć ich faktycznie zastosowanie i wpływ na element.

Pobieranie – Gotowy program

[to_like]

QuickTip#8 – Marek Winiarski

[/to_like]

Podoba Ci się? Udostępnij!