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

Dzisiejszy odcinek: Jak zrobić responsywne menu teksturowe

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

Jakiś czas temu dyskutowaliśmy już na temat jak zrobić menu. Jednak wtedy, interesowało nas skalowalne menu, oparte na GUISkin i dynamicznie tworzonych przyciskach. Dzisiaj, omówimy sobie bardziej efektowną, ale bardziej pracochłonną metodę, czyli menu oparte na plikach tekstur.

Przygotowanie

Do stworzenia całości potrzebujemy przede wszystkim plików tekstur dla przycisków. Dla każdego przycisku teksturę normalną i po najechaniu. Dodatkowo, dla efektu, przyda się jakiś dźwięk kliknięcia.

Po dodaniu tekstur do projektu (np. przez przeciągnięcie ich z okna Windowsa – czy innego systemu – do panelu Project w Unity), musimy zmienić ich opcję importu. Wybieramy każdą teksturę i w panelu Inspector, zmieniamy Texture Type na GUI.

Import tekstur
Import tekstur

Kolejną rzeczą, będzie dodanie do sceny 3 obiektów, typu GUITexture – po jednym na każdy przycisk. Zostaje nam wypełnić odpowiednio ich pola. Interesują nas 3 rzeczy. Po pierwsze pole Texture, gdzie wrzucamy domyślną teksturę dla przycisku. Po drugie, wartości W i H dla parametru Pixel Inset. Podajemy tam oryginalny rozmiar naszej tekstury – u mnie tekstury mają 150px na 30px. Ostatnie co zmienimy to pozycję X i Y dla komponentu transform. Podajemy wartości z przedziału od 0 do 1. Można określić, że np. wartość 0.1 = 10%. Kryje nas to przy różnych rozdzielczościach ekranu. Wartości te liczone są od lewego dolnego rogu. Dlatego, ja chcąc mieć menu w lewym górnym ustawiłem X na 0.1 i Y na 0.9 (każdy kolejny przycisk jest o 0.05 niżej).

Ustawienia obiektu GUITexture
Ustawienia obiektu GUITexture

Ostatni krok przygotowań, to utworzenie skryptu. Mój nazywa się btnScript.cs. Stworzony skrypt dodajemy do każdego elementu typu GUITexture. Przechodzimy do edycji skryptu.

Skrypt

Zaczniemy oczywiście od deklaracji zmiennych:

public Texture2D btnOff;
public Texture2D btnOn;
public AudioClip beep;
public string levelToLoad;

Pierwsze dwie to nasze tekstury przed i po najechaniu. Trzecia to odtwarzany dźwięk, a ostatnia będzie przechowywać nazwę poziomu, do którego mamy się przenieść.

Z racji, że będziemy używać dźwięku, narzucamy wymaganie komponentu Audio Source, przez linijkę nad deklaracją klasy:

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(AudioSource))]
public class btnScript : MonoBehaviour {

Teraz szybko zajmiemy się zmianą tekstury po najechaniu myszką.

void OnMouseEnter()
{
	guiTexture.texture = btnOn;
}

void OnMouseExit()
{
	guiTexture.texture = btnOff;
}

Sprawa jest więcej niż oczywista. Gdy myszka wjedzie nad obiekt, ustawiamy mu teksturę ON, a kiedy myszka wyjeżdża z obiektu, ustawiamy teksturę OFF. Z racji, że skrypt jest przypisany bezpośrednio do GUITexture, możemy się łatwo odwoływać do komponentu texture.

Czas na kliknięcie.

IEnumerator OnMouseUp()
{
	audio.PlayOneShot(beep);
	yield return new WaitForSeconds(0.4f);
	if(levelToLoad == "Quit") {
		//Application.Quit();
		Debug.Log("Exit!");
	} else {
		//Application.LoadLevel(levelToLoad);
		Debug.Log("Load Level: " + levelToLoad);
	}
}

Używamy funkcję OnMouseUp, czyli wywołującą się gdy ściągamy palec z klawisza myszki. Funkcja zamiast Void, zwraca IEnumerator, co sprawia, że wspiera operację współdzielenia czasu procesora. Tym samym, możemy łatwo odmierzyć sobie czas za pomocą funkcji WiatForSeconds. Ale po kolei. Najpierw odtwarzamy nasz dźwięk. Następnie oczekujemy. Dzięki temu, dźwięk kliknięcia zdąży się odegrać, zanim zostaniemy przeniesieni do nowej sceny.

Teraz sprawdzamy warunek. Jeśli poziom do którego mamy sięprzenieść to Quit, oznacza, że wyłączamy grę. W przeciwnym wypadku ładujemy poziom. Konkretne funkcję wykomentowałem i zastąpiłem logami w konsoli, aby było widać efekt działania, bez konieczności tworzenia oddzielnych scen.

Responsywność

Obiecałem menu dostosowujące się do rozdzielczości. Tak naprawdę możemy jedynie dostosowywać w dół. Rozciąganie tekstury w górę, zakończy się tym, że będzie brzydka i rozpikselowana. Dlatego, najpierw musimy sobie założyć maksymalną rozdzielczość ekranu jaką obsłużymy. Będzie to punkt zerowy, dla którego dedykowane będą tekstury. Ja ustawiłem je na rozdzielczość mojego monitora.

private int defaultScreenW = 1680;
private int defaultScreenH = 1050;

Teraz zostaje zmienić parametry PixelInset w momencie ładowania tekstury, czyli w funkcji start:

void Start()
{
	guiTexture.pixelInset = new Rect(
			guiTexture.pixelInset.x,
			guiTexture.pixelInset.y,
			(Screen.width * guiTexture.pixelInset.width) / defaultScreenW,
			(Screen.height * guiTexture.pixelInset.height) / defaultScreenH
}

Pierwsze dwa parametry zostawiamy w spokoju, zmieniając tylko wysokość i szerokość. Obliczamy to z prostej proporcji.

Wykończenie

Zostało już tylko wrócić do Unity i uzupełnić wszystkie publiczne zmienne odpowiednimi teksturami, dźwiękiem i opisami poziomów. Przy czym trzeba pamiętać, że przycisk wyjścia powinien mieć zmienną levelToLoad ustawioną na “Quit”.

Download – Kompletny projekt

[to_like]

QuickTip#16

[/to_like]