Marek Winiarski

Klasa GUI w Unity

Klasy(czne) Unity3d to seria w której omawiam podstawowe klasy dostępne w Unity3d. Omawiam do czego dana klasa służy i jakie fajne funkcję posiada.

Dzisiejszy odcinek: Klasa GUI.

Klasę GUI możemy rozwinąć jako Graphic User Interface, czyli po naszemu: Graficzny Interfejs Użytkownika. Większość z nas, skojarzy to z paskiem życia postaci, menu budowy jednostek, czy menu w grze. Skojarzenia będą całkiem dobre, ale nie w Unity.

Unity do tego celu wykorzystywało klasę GUI, ale do swojej 4 edycji. Wraz z częścią czwartą pojawił się Canvas, oraz klasa UI. Unity zaleca wykorzystanie właśnie tych narzędzi przy tworzeniu czy to menu, czy to HUDa, czy innych elementów graficznych, które możemy podpiąć pod interfejs graficzny.

No dobra, to co w takim razie z GUI? Zostało wyłączone z obiegu i nie powinniśmy go używać? W takim przypadku tego wpisu by nie było.

Do czego mi klasa GUI?

Zgodnie z dokumentacją Unity, klasa GUI ma dokładnie 3 przeznaczenia:

O co tutaj chodzi? Skrypty w Unity obsługują pewną szczególną funkcję: OnGUI. Taka funkcja pozwala stworzyć graficzny interfejs dla skryptu w locie. W klasycznej sytuacji, musielibyśmy postawić canvasa, dodać mu elementy takie jak przyciski i opisy, potem napisać skrypty, które obsłużyłyby przyciski i dopiero coś z tym zrobić. Dzięki klasie GUI, możemy to wszystko zamknąć w jednym skrypcie. Zyskujemy dzięki temu dwie rzeczy:

W ten sposób możemy sobie też tworzyć szkice naszych docelowych menu. Można je napisać szybko i już sprawdzać ich funkcjonowanie.

Podkreślę jeszcze raz. Tak wykonane menu, nie powinno trafić do końcowego gracza.

Jak wykorzystać klasę GUI?

W zasadzie całe wykorzystanie klasy GUI sprowadza się do tworzenia elementów interfejsu wewnątrz funkcji OnGUI. Najbardziej podstawowy skrypt, będzie wyglądał tak:

using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {

    void OnGUI () {
        // Tutaj Kod
    }

}

Oczywiście, taki kod nic nie robi.

Nie będę omawiał po kolei każdej funkcji dostępnej w klasie GUI. Od tego w zasadzie jest dokumentacja. Natomiast zaprezentuję wam kilka podstawowych rzeczy, oraz streszczę, co jeszcze możecie dzięki tej klasie zrobić.

Podstawowe zastosowania

Wg. mnie dwie najpowszechniejsze metody wykorzystania GUI, będą sprowadzały się do tworzenia prostych menu przyciskowych – do tworzenia pozorowanego menu, prostego panelu testowego czy przycisków wyzwalających akcję. Oraz do wyświetlania danych w ten czy inny sposób w celu debugowani. Dlatego, te dwie metody omówię.

Zaprezentowany kod, będzie pochodził z dokumentacji. Omówienie będzie moje.

Przyciski

using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
                
    public Texture2D icon;
    
    void OnGUI () {

        // Przycisk z ikona
        if (GUI.Button (new Rect (10,10, 100, 50), icon)) {
            print ("Ikona zostala kliknieta");
        }
    
        // Klasyczny przycisk z tekstem
        if (GUI.Button (new Rect (10,70, 100, 20), "Tresc Przycisku")) {
            print ("Przycisk zostal klikniety");
        }

    }

}

Zaczynamy od przycisków. Są tutaj dwa warianty. Przycisk tekstowy, oraz przycisk z ikoną zamiast treści. Wykorzystujemy tutaj funkcję Button. Przyjmuje ona dwa parametry: Pierwszy to obiekt typu Rect, a drugi to odpowiednio string z treścią przycisku, lub obiekt typu Texture2D reprezentujący ikonę.

Obiekt typu Rect ma 4 parametry konstruktora. Pozycję na ekranie, oraz wysokość i szerokość. Wygląda to tak: new Rect(x, y, szerokość, wysokość). Pozycja x i y odnosi się do lewego górnego rogu przycisku, a punktem (0, 0) jest lewy górny róg ekranu.

[stextbox id=”info” defcaption=”true”]Przy ustalaniu pozycji elementów przydatne mogą być zmienne: Screen.height oraz Screen.width, które zawierają odpowiednio wysokość i szerokość ekranu.[/stextbox]

Drugą zastanawiającą rzeczą może być: Dlaczego przyciski są wewnątrz ifa? Musimy pamiętać, że w tym przypadku Button jest funkcją, która zwraca true lub false. True pojawia się, gdy przycisk został kliknięty. Dzięki temu, wewnątrz ifa możemy rozpisać akcję, która ma się wykonać gdy ktoś kliknie dany przycisk.

Ciekawostką mogą być tutaj jeszcze dwie inne funkcję:

Toolbar, która wyświetla nam przyciski jako listę jeden obok drugiego, jak w typowym pasku narzędzi:

Unity Toolbar

Oraz grid, który wyświetla nam siatkę przycisków.

Unity Grid
using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {

    // Zmienne Toolbara
    public int toolbarInt = 0;
    public string[] toolbarStrings = new string[] {"Toolbar1", "Toolbar2", "Toolbar3"};

    // Zmienne Grida
    private int selectionGridInt = 0;
    private string[] selectionStrings = {"Grid 1", "Grid 2", "Grid 3", "Grid 4"};

    void OnGUI() {
        // Tworzymy Toolbar
        toolbarInt = GUI.Toolbar(new Rect(25, 25, 250, 30), toolbarInt, toolbarStrings);

        // Tworzymy Grid
        selectionGridInt = GUI.SelectionGrid (new Rect (25, 25, 300, 60), selectionGridInt, selectionStrings, 2);
    }
}

Część kodu jest nam znana. Zmiany są dwie. Pojawia się zmienna typu int toolbarInt oraz selectionGridInt. Są to zmienne mówiące, który przycisk jest wciśnięty (będzie oznaczony jako wciśnięty). Druga zmiana, to fakt, że treść przycisku zastąpiła tablica z treściami.

W przypadku Grida, mamy dodatkowy parametr na samym końcu. Mówi on, ile kolumn ma się wyświetlić.

Ważna rzecz: Obie funkcję zwracają nam inta. Int mówi o tym, który przycisk został wciśnięty. Więc tutaj o tym jakie akcję będą wykonane nie decyduje if, którym obejmujemy grida czy toolbara, a jakiś switch umieszczony później.

Wypisanie tekstu

Tutaj sprawa jest w sumie jeszcze prostsza, niż w przypadku przycisku. Oto kod:

using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
            
    public Texture2D icon;
    public int zm;

    void OnGUI () {
        // Etykieta z tekstem
        GUI.Label (new Rect (0,0,100,50), "Tutaj jakas tresc dla etykiety");

        // Etykieta z obrazkiem
        GUI.Label (new Rect (0,0,100,50), icon);

        // Etykieta wypisujaca wartosc zmiennej
        GUI.Label (new Rect (0,0,100,50), "Zmienna zm = " + zm);
    }

}

Do wyświetlenia treści służy funkcja Label (etykieta). Nie ma tutaj nic, co mogłoby nas zaskoczyć. Znów klasa Rect decyduje o położeniu etykiety, a jako drugi parametr podajemy treść etykiety (również możemy podać teksturę).

Jeśli chcemy wypisać zawartość jakiejś zmiennej, obowiązują nas te same zasady łączenia stringów, co normalnie.

Możemy sobie też wyrysować dowolną teksturę:

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    public Texture aTexture;

    void OnGUI() {
        GUI.DrawTexture(new Rect(10, 10, 60, 60), aTexture);
    }
}

Ponownie sprawa jest prosta, pozycja i sama tekstura.

Inne przydatne funkcje

Ogólnie klasa GUI dysponuje funkcjami pozwalającymi tworzyć różne formularze i nie tylko. Po za przyciskami klasycznymi, mamy funkcję Toggle, która wyświetla przycisk mający stan włączony lub wyłączony. Mamy klasy TextField, TextArea i PasswordField, które tworzą nam opcję generowania formularza takiego jak w internecie.

Mamy też HorizontalSlider i VerticalSlider, czyli kontroli tworzące suwaki do zmiany wartości w założonym przedziale.

Całość możemy ładnie opakować wykorzystując klasy Window i Box, tworzące odpowiednio okienko i prostokąt do zbierania treści.

Dostosowanie wyglądu

Ogólnie nasze wytwory będą całkiem ładne i estetyczne. Ale to ciągle domyślny wygląd Unity. Możemy sobie takie kontrolki dostosować po swojemu. Służy do tego klasa GUISkin. Możemy sobie obiekt tej klasy utworzyć w edytorze klikając w panelu Hierarchy prawym przyciskiem i wybierając: Create -> GUISkin. Samo ustawienie kontrolek możemy dostosować w oknie inspektor, po wybraniu utworzonego obiektu w panelu hierarchy.

Modyfikacja obiektu GUISkin w inspektorze. Źródło: https://docs.unity3d.com/
Modyfikacja obiektu GUISkin w inspektorze.
Źródło: https://docs.unity3d.com/

Możemy sobie modyfikować tutaj różne śmieszne parametry dla kontrolek w różnych sytuacjach. W spoczynku, po najechaniu, marginesy, obramowania etc. Jeśli ktoś liznął kiedykolwiek HTMLa i CSSa to będzie się tu czuł jak ryba w wodzie.

No to mamy już ten obiekt, ale jak go wykorzystać?

using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
                    
    public GUISkin mySkin;
    private bool toggle = true;
    
    void OnGUI () {

        // Ustawiamy skorke
        GUI.skin = mySkin;
    
        // Ten przycisk, będzie zgodny z ustawieniami naszej skroki
        GUI.Button (new Rect (10,35,150,20), "Ostylowany przycisk");
    
        // Ustawienie skorki na null przywraca domysle wartosci Unity. Moglibysmy tutaj podac np. drugi obiekt GUISkin
        GUI.skin = null;
    
        // Ten przycisk powstanie juz jako przycisk o klasycznym wygladzie Unity
        GUI.Button (new Rect (10,75,150,20), "Klasyczny Przycisk");
    }
        
}

Taki obiekt podajemy sobie po prostu jako zmienną publiczną, a następnie przypisujemy do zmiennej skin klasy GUI. Wszystkie elementy GUI utworzone po przypisaniu skórki będą generowane w jej stylu. Możemy wewnątrz jednej funkcji OnGUI zmieniać skórkę wielokrotnie. Jeśli chcemy powrócić do klasycznego wyglądu Unity, wystarczy zmiennej skin przypisać wartość null.

Podsumowanie

Tyle istotnych kwestii związanych z klasą GUI. Pozwala nam szybko stworzyć sobie proste menu czy to dla narzędzi developerskich czy jako interfejs wtyczki, czy po prostu do debugowania czy prototypownia. Najważniejsze co musimy pamiętać to fakt, żeby tak przygotowany interfejs nie trafił do końcowego użytkownika. Nie jest to najlepsze rozwiązanie, a do tego daje mniejsze pole manewru w kwestii wyglądu, niż przeznaczona do tego klasa UI.

Exit mobile version