Klasy(czne) Unity to seria w której omawiam podstawowe klasy dostępne w Unity. Omawiam do czego dana klasa służy i jakie fajne funkcję posiada.
Dzisiejszy odcinek: Klasa Input
Gry są medium interaktywnym. To ich główna przewaga nad filmami czy książkami, gdzie jesteśmy jedynie obserwatorem wydarzeń, a nie możemy w nich uczestniczyć. Uczestnictwo w wydarzeniach gry odbywa się przez urządzenia peryferyjne wejściowe. Mamy tutaj na myśli tak oczywiste rzeczy jak myszka, klawiatura czy pad, ale również rzeczy mniej intuicyjne, takie jakie jak: eran dotykowy telefonu, czy żyroskop, aż po rzeczy których możemy się całkiem nie spodziewać, czyli: mikrofon i kamera.
Żeby odebrać dane od użytkownika w Unity posługujemy się klasą Input, którą możemy na polski tłumaczyć jako: “wejście”.
Do czego mi klasa Input?
Jak już wspomniałem, za pomocą klasy Input pobieramy dane od użytkownika i to jest główny cel istnienia tej klasy, aczkolwiek nie jedyny. Drugim jej atutem jest uczynienie danych wejściowych niezależnych od urządzenia z którego korzysta gracz, oraz ułatwienie konfiguracji kontrolerów.
Pierwszy cel jest raczej oczywisty. Odczytywanie danych od gracza, tutaj nie ma czego tłumaczyć.
Druga kwestia, czyli jak klasa Input sprawia, że dane są niezależne od urządzenia wejściowego? Jeżeli zajrzymy do konfirugarcji (Input Manager) [Edit -> Preferences -> Input], to zobaczymy tam listę elementów, takich jak: Horizontal, Vertical, Fire 1, Fire 2, Jump etc. Właśnie tymi hasłami będziemy się posługiwać w kodzie gry. Dzięki temu nie interesuje nas czy za przyciskiem Fire 1 stoi lewy klawisz myszy, czy może przycisk ctrl, albo jakiś przycisk na padzie. My w grze wiemy, że po naciśnięciu Fire 1 ma się coś wydarzyć. Czym on jest, już nas nie musi interesować.
Ostatnia kwestia to ułatwienie konfiguracji. W managerze mamy spore opcje definiowania czym jest dany “przycisk”. Dzięki temu nam jest łatwo skonfigurować podstawowe sterowanie. Dodatkowo gracz, może sobie dostosować sterowanie samemu w czasie uruchamiania gry.
Problem jest jeden. Mimo próśb od użytkowników od roku 2009, do dzisiaj Unity nie wprowadziło opcji zmiany sterownia w trakcie trwania gry. Jedyna opcja, żeby takie coś osiągnąć to napisanie swojego Input Managera od zera – lub skorzystać z jakiegoś istniejącego rozwiązania.
Jak wykorzystać klasę Input?
Jak już się łatwo domyślić, klasę Input będziemy wykorzystywać do pobierania danych od użytkownika. Do rozważenia mamy dwie kwestię. Konfirugrację oraz samo zastosowanie klasy.
Jest jedna ważna kwestia odnośnie zastosowania. Wszystkie flagi przycisków są resetowane po załadaniu nowej klatki. Tym samym wszystkich funkcji dotyczących klasy Input należy używać jedynie wewnątrz funkcji Upade.
Konfiguracja
Zaczniemy od samej konfiguracji, bo jest ona dość prosta. Aby uruchomić Input Managera, wybieramy z górnego menu: Edit -> Preferences -> Input. W okienku Inspector otworzy nam się wspomniany Manager. Po rozwinięciu jednej z opcji możemy dokonać jej konfiguracji. Oczywiście, możemy też dodać własną (kolejną) opcję. Wystarczy zmienić wartość rozmiaru tablicy (Size) na samej górze okienka.
Każdą z opcji, będę nazywał przyciskiem – nie jest to do końca precyzyjne określenie, bo takim “przyciskiem” może być gałka analogowa, ale brzmi to krócej niż “dowolne urządzenie wejściowe” albo coś takiego.
Przeanalizujmy, co możemy sobie skonfigurować:
- Name – Nazwa tego przycisku. Będzie istotna po stronie kodowej, bo to za pomocą tej nazwy, będziemy się odwoływać do tego przycisku,
- Descriptive Name / Descriptive Negative Name – Opisowa nazwa pozycisku. Widoczna tylko w konfiguracji przycisków przed uruchomieniem gry. Ma pozwolić graczowi lepiej zrozumieć co sobie ustawia.
- Positive Button / Negative Button – Klawisz pozytywny i negatywny. Jeżeli naciśniemy przycisk pozytywny to sprawdzenie wartości dla tego przycisku zwróci wartość 1, jeżeli naciśniemy negatywny to dostaniemy wartość -1.
- Alt Positive Button / Alt Negative Button – W zasadzie to samo co wyżej, tylko dajemy drugą opcję korzystania ze sterownia. W przykładzie ze zdjęcia, możemy poruszać się do przodu i tyłu korzystając z konfiguracji klawiszy: w i s, albo strzałek w górę i dół.
- Gravity – Liczba jednostek na sekundę w których przycisk powróci do stanu neturalnego, czyli do zwracania wartości 0.
- Dead – Ważne w przypadku gałek analogowych. Dopiero po przekroczeniu podanej tutaj wartości, Unity uzna, że gałka została ruszona.
- Sensitivity – Również ważne dla urządzeń takich jak gałka analogowa. Określa o ile jednotek na sekundę, wartość ma się zbliżać do wartości wybranej przez gracza. Czyli gdy stan neutralny to 0, a gracz przesunie gałkę do pozycji 1, to zmieniając tą wartość na np.: 0.01 zajmie nam sporo czasu, zanim wartość zwracana będzie wynosić 1, mimo że gałka jest już faktycznie w takiej pozycji.
- Snap – Jeśli zaznaczmy tą opcję, to przycisk zwróci wartość zero, gdy jednocześnie klikniemy klawisz pozytyny i negatywny.
- Invert – Zamienia miejscami przycisk pozytywny z negatywnym. W przykładzie z obrazka, domyślnie “w” zwraca 1, a “s” -1, gdyby zaznaczyć Invert, to “w” zwróci -1, a “s” 1.
- Type – Jakie rodzaje danych wejściowych będzie kontrolował ten przycisk. Możemy wybrać mysz, joystick albo kombinację myszki i klawiatury.
- Axis – Którą oś urządzenia będziemy kontrolować. Mamy domyślnie osie X i Y, oraz Z (jako scroll myszki) i wiele kolejnych osi, dla padów.
- Joy Num – Numer pada, którego dotyczy dany przycisk.
To chyba wystarczy, ale zostaje jedna kwestia. Wiemy jak sobie skonfigurować całość, ale jak się odwołać do niektórych klawiszy, np. do klawiatury numrycznej, strzałek czy przycisków na padzie, albo przycisków myszki.
Sprawa jest prosta dla znaków alfanumerycznych z “głównej” częsci klawiatury, bo tam podajemy wprost: a-z, 0-9 i f1-f12. Jeżeli chodzi o inne konfigurację:
- Strzałki: up, down, left, right
- Klawisze na klawiaturze numerycznej: [0], [1], [2], [+], [equals]
- Klawisze modyfikujące: left/right alt, ctrl, shift, cmd. Np.: left alt
- Klawisze myszki: mouse 0, mouse 1, mouse 2, …
- Klawisze specjalne: backspace, tab, return, escape, space, delete, enter, insert, home, end, page up, page down.
- Przyciski joysticka: joystick button 0, joystick button 1, joystick button 2, …
Może się zdarzyć, że dopuszczamy multiplayer na jednym komputerze, gdzie gracze mają podpiętych kilka padów. Możemy wtedy je rozróżnić, korzystając z konstrukcji: joystick 1 button 0, joystick 1 button 1, joystick 1 button 2, …
Tyle o smaej konfiguracji, zobaczymy jak to wykorzystać w kodzie.
Podstawowe zastosowania
W zasadzie nie ma tutaj cudów, bo jak mówiłem, klasa Input służy do obierania danych od gracza, więc większość jej funkcji to zwracanie pewnej wartości. Przyjrzymy się tym najprzydatniejszym i najciekawszym.
PC i Konsole
Jeżeli chodzi o konwencjonalne narzędzia wejściowe jakimi są pady, myszy i klawiatury, to większość załatwi nam kilka podstawowych funkcji:
Input.GetButton ("Fire 1"); Input.GetButtonDown ("Fire 1"); Input.GetButtonUp ("Fire 1");
Pozornie do siebie podobne, ale różne. Ogólnie wszystkie służą do wykrycia naciśnięcia przycisku. W tym wypadku tego, opisanego jako Fire 1, co możemy w managerze sprawić, że przekłada się na lewy klawisz myszki, albo lewy ctrl.
Nasuwa się pytanie, co zmeinia Down albo Up przy funkcji? GetButtonDown wykonuje się w momencie kliknięcia przycisku, czyli gdy następuje styk. Będzie pewnie najczęściej wykorzystywanym wariantem. Od razu widać gdzie pasuje: skok, strzał, użycie przedmiotu. Dokładnie w jednej klatce, kiedy następuje wciśnięcie zwraca true.
GetButtonUp uruchomi się, gdy puścimy klawisz. Tutaj jako wykorzystanie nasuwa się np. silny atak. Gdy przytrzymamy klawisz myszki to zbieramy energię i dopiero po puszczeniu klawisza wykonywany jest atak. Również trwa jedynie przez jedna klatkę i w tej klatce zwraca true.
Apropos przytrzymania klawisza, to właśnie GetButton zwraca true w sytuacji, gdy przycisk trzymamy. Ogólnie funkcje
Druga przydatna funkcja to:
Input.GetAxis ("Horizontal");
Zwraca nam ona liczbę zmiennoprzecinkową (float) z przedziału od -1 do 1. Kiedy trzymamy pozytywny klawisz, liczba będzie się zbliżać do 1, gdy negatywny to do -1. Od wartości Sensitivity w ustawieniach przycisku zależy, jak szybko wartość przemieści się z netralnej wartości 0 (sugerującej, że nic nie jest naciskane czy przechylane w przypadku gałki anaglowej) do wartości 1 lub -1. Wartość gravity natomiast, określi jak szybko z wartości -1 lub 1 wrócimy do wartości 0.
Kiedy wykorzystać GetAxis, a kiedy GetButton? GetAxis zalecany jest do wykorzystania, kiedy mamy ustawiony przycisk pozytywny i negatywny. Dzięki temu w wielu przypadkach oszczędzimy kilka linijek kodu i poprawimy jego czytelność. Czyli najczęściej będzie to wszelkiego rodzaju ruch.
Jako ciekawostka, dodam jeszcze, że można się odwołać całkowicie bezpośrednio do konkretnego klawisza na klawiaturze czy myszcze:
Input.GetKey ("a"); Input.GetKey (KeyCode.A); Input.GetMouseButton(0);
Oczywiście obie kombinację występują z dodatkami Down i Up. Jako parametr funkcji GetKey podajemy bezpośrednio przycisk, który nas interesuje. Możemy podać go dwojako, albo wykorzystując klasę KeyCode, która podpowie nam przyciski, albo podając przycisk wprost. Natomiast parametr funkcji GetMouseButton to numer przycisku myszy. 0 = lewy przycisk myszy, 1 = prawy przycisk myszy.
Obu funkcji raczej niezalecam stosować. Dużo lepsze rozwiązanie to wykorzystać funkcję Button, które dają sporą dozę kontroli nad przyciskami. Gdy kożystamy z GetKey, gracz nie może zmienić klawiszologii, co często będzie działaniem nieporządanym. Jeśli moja porada to mało, to dodam iż Unity również zaleca stosować wersję z Button.
Mobilne
W urządzeniach mobilnych jest nieco inczaj. Kwestia pierwsza to oczywiście ekran dotykowy. Tutaj podam przykład zastosowania:
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) { Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition; }
Zmienna statyczna touchCount zwraca nam ile punktów ekranu jest aktualnie dotykanę. Przekłada się to najczęściej na liczbę palców. Funkcja GetTouch(x) pobiera nam dane danego dotykanego punktuu, gdzie x to numer dotyku.
Teraz mamy dwie ważne zmienne dotyczące samego dotyku: phase, czyli faza. Faz mamy 5:
- Began – palec dotknął ekranu,
- Move – palec porusza się po ekranie,
- Stationary – palec dotyka ekranu, ale się nie rusza,
- Ended – palec przestaje dotykać ekranu,
- Canceled – system przerwał śledzenie palca.
Druga zmienna to deltaPosition, czyli zmiana położenia palca względem ostatniej klatki. Inne ciekawe parametry dotyku to: position, czyli pozycja pozycja w układzie współrzędnych, oraz tapCount, czyli liczba tapnięć ekranu wykonana przez palec.
Druga sprawa na urzędzeniach mobilnych to wszelkie urządzenia pomiarowe. Unity obsługuje 3: Akcelerometr, Kompas i Żyroskop.
Odpowiadają za to 3 zmienne statyczne:
Vector3 a = Input.acceleration; Compass c = Input.compass; Gyroscope g = GyroInput.gyro;
Akcelometr zwraca nam wektor, mówiący o przyspieszeniu w każdej osi. Jeśli nie ruszamy telefonem, powinien zwrócić wektor zerowy.
Compass i Żyroskop mają swoje oddzielne obiekty. To co jest ważne w przypadku obu to skorzystać ze zmiennej enabled, żeby upewnić się, że dane urządzenie zostało włączone.
W przypadku kompasu mamy dwie ciekawe moim zdaniem zmienne:
Compass.trueHeading Compass.magneticHeading
Pierwsza zwraca nam kąt między przodem telefonu, a geograficzną północą, natomiast druga kąt między przodem telefonu, a magnetyczną północą. Kąt oczywiście w stopniach.
Natomiast w żyroskopie, ciekawe zmienne to:
Gyroscope.attitude Gyroscope.userAcceleration Gyroscope.rotationRateUnbiased
Attitude to loklizacja telefonu w świecie, określona przez żyroskop. userAcceleration to przyspieszenie nadane w danej osi przez użytkownika, zawarta w wektorze 3 elementowym. Czyli, gdy kiwamy telefonem na boki, to dostaniemy odpowiednie wartości w osi Y wektora. rotationRateUnbiased to natoamist wektor 3 elementowy, który zawiera informację o prędkości obrotu telefonu w danej osi.
W klasie Input mamy jeszcze jedną ciekawą zamienną, która domyślnie jest włączona:
Input.simulateMouseWithTouches
Jeżeli ta zmienna ustawiona jest na true, to możemy za pomocą tapnięć symulować myszkę. Jedno dotknięcie = kliknięciu w lewy przycisk myszy, dwa szybkie dotyknięcia to jak kliknięcie w prawy klawisz myszki etc.
Podsumowanie
To tyle na dziś. Mam nadzieję, że dzięki tym informacją sterowanie w waszych grach będzie nienaganne. Oczwyiście zawsze zachęcam do samodzielnego analizowania dokumentacji, bo podane przeze mnie informację, to nie pełny zestaw możliwości tej klasy, a jedynie jej najprzydatniejsze i najciekawsze funkcję.