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

Dzisiejszy odcinek: Jak zdebugować grę w Unity3d.

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

Teoria

Ostatnio rozmawialiśmy o debugowaniu skryptów. Jednak robienie gry to nie tylko skrypty, a czasami układanie elementów, które nie chcą współpracować. Często mają też powiązanie ze skryptami. Np. coś miało się pojawić, ale tego nie robi. Coś miało zniknąć, ale siedzi dalej. Coś miało się stać, ale dzieje się co innego. Promień miał lecieć prosto, leci po ukosie. Dziś zaprezentuję wam kilka metod, które powinny pomóc wam znaleźć winowajcę w większości przypadków.

Coś się miało stać, a się nie dzieje

Problem dotyczy w sumie skryptów. Czasami dzieje się tak, że jakiś kawałek kodu nie działa, ale nie dostajemy po twarzy żadnym błędem czy ostrzeżeniem. Co wtedy? Śmiem twierdzić, że w większości przypadków, fragment kodu, który nie działa jest bogaty w ify, pętle i wywołania funkcji.

Co zrobić?

Rozwiązanie jest w sumie proste. Unity oferuję nam funkcję o nazwie: Debug.Log(Object tekst); O co w niej chodzi? Wypisuje ona w konsoli, to co podamy jako tekst (mogą być tam zmienne, czy wywołania funkcji). No dobra, ale po co nam to? Sprawa jest prosta. Jeśli wywołujesz jakąś funkcję, albo masz dużo ifów, powstawiaj sobie kilka takich linijek z różnymi tekstami i sprawdź, dokąd skrypt dochodzi. W przypadu ifów, możesz przed ifem wypisać sobie składowe warunku – może nie został spełniony, mimo że wydaje Ci się, że został.

Przykład:

if (Physics.Raycast(transform.position, fwd, out hit)) {
	if(hit.transform.tag == "Enemy" && hit.distance < range) {

	}
}

Jest to fragment kodu, z tutoriala FPS. Załóżmy, że kod wewnątrz naszego ifa, nie wykonuje się. Co możemy zrobić?

Debug.Log(transform.position + " - " + fwd);
if (Physics.Raycast(transform.position, fwd, out hit)) {
	Debug.Log("Tag: " + hit.transform.tag);
	Debug.Log(hit.distance + " < " + range);
	if(hit.transform.tag == "Enemy" && hit.distance < range) {
		Debug.Log("Jestem!");
	}
}

Co nam to daje? Najpierw możemy sobie sprawdzić z jakiej pozycji i w jaką stronę strzelamy promieniem. (Później opiszę lepszą metodę sprawdzania promienia). Później wewnątrz ifa, mamy warunki wewnętrznego. Jeżeli się wypiszą, to wiemy, że pierwszy if jest OK. Przy okazji, możemy sprawdzić czy warunki kolejnego są spełnione. (Np. dzięki temu zauważyłem, że range miał za małą wartość i żeby trafić przeciwnika, musiałem stać niemal przy nim). Pojawienie się ostatniego logu mówi nam, że oba ify nie zawiodły i błąd jest gdzieś indziej.

Akurat w tym szczególnym wypadku problemem może być pierwszy if, ponieważ mamy w nim rzutowanie promienia.

Rzutowanie promienia

Promieniowi podajemy źródło z którego leci oraz kierunek. Więc problemem może być w sumie tylko to, że promień leci ze złego miejsca, albo w złą stronę.

Co zrobić?

Jak to sprawdzić? Z pomocą przychodzi kolejna funkcja z klasy Debug: Debug.DrawRay(Vector3 start, Vector3 kierunek, Color kolor); Składnia jest taka sama jak funkcji Physics.Raycast. Czyli podajemy punkt startowy, kierunek (odpowiednio przemnożony, aby linia była długa), ale zamiast zmiennej referencyjnej, podajemy kolor. Co nam to da? Ano coś takiego:

Przykład:

Debugowanie rzucania promienia
Debugowanie rzucania promienia

Powstało to mniej więcej z takiego skryptu:

Transform tf = transform.parent.GetComponent<Transform>();
fwd = tf.TransformDirection(Vector3.forward);
Debug.DrawRay(tf.position, fwd * 10, Color.red);

Już wyjaśniam. tf, to komponent transform kamery, dzięki temu promień leci ze środka kamery. fwd, to przód kamery, dzięki temu promień leci tam gdzie patrzy kamera. Kolory daje nam obiekt Color, gdzie jak widać łatwo się odwołać do konkretnego koloru, z resztą MonoDevelop kolory podpowiada.

Jest jeszcze wariancja na temat Debug.DrawRay, a mianowicie: Debug.DrawLine(Vector3 start, Vector3 koniec, Color kolor); Czym się różni? Zamiast kierunku, podajemy punkt końcowy i linia pędzi z punktu startowego do końcowego.

Linie są widoczne tylko w okienku Scene!

Znikające elementy

Sprawa intuicyjna. Czyli coś dodaliśmy, ale tego nie ma. Mamy dwa przypadki. Mogliśmy to dodać z kodu, albo jako oddzielny obiekt. W przypadku obiektu który dodaliśmy na sztywno, przypadek taki najczęściej nas spotka przy obiektach GUI. Łatwo się walnąć w pozycji i pojawić obiekt gdzieś po za ekranem.

Co zrobić?

Najprościej, ustawić sobie podgląd na okienko Game, a następnie wstawić jakąś wartość na sztywno. Np. gdy sprawdzamy obiekt tekstowy, wprowadzić jakikolwiek tekst, a następnie manipulować pozycją, tak żeby zobaczyć tekst. Prostackie, ale działa.

W przypadku kodu, jednym z problemów może być fakt, że skrypt nie dochodzi do funkcji Instantinate – wtedy stosujemy techniki z pierwszego akapitu. Ale załóżmy, że obiekt obiekt się pojawia (mamy go w panelu Hierarchy).

Tutaj znów mamy dwa przypadki. Jeżeli operujemy na GUI, to odpalmy skrypt, pozwalamy obiektowi się pojawić i majstrujemy w jego opcjach, do póki go nie zobaczymy. Można też wprowadzić przykładową wartość, jeśli nasz obiekt jest początkowo pusty.

Jeżeli nie pojawia się kompletny obiekt (np. przeciwnik), to jest szansa, że skrypt pojawia nam go w dziwnym miejscu. Dlatego pozwalamy skryptowi na utworzenie obiektu, zaznaczamy go w panelu Hierarchy, przechodzimy do okienka Scene i naciskamy na klawiaturze “F”. Przycisk ten centruje nam widok na obiekcie, dzięki czemu go znajdziemy i możemy określić co jest nie tak.

Podsumowanie

W połączeniu z poprzednim poradnikiem, ten wpis powinien pozwolić Ci na odnalezienie i rozwiązanie większości typowych i częstych błędów. Niestety są to jedyne dość uniwersalne techniki. Jeśli zawarta w tych wpisach wiedza, nie pozwala Ci rozwikłać problemu są dwie opcję. Albo coś przeoczyłeś, albo Twój problem jest bardziej złożony lub nietypowy. Jednak, do póki pracujesz nad prostymi projektami, powinny Ci w zupełności wystarczyć.

Co jeśli i one zawiodą? Zostaje społeczność. Pytaj ludzi na forach, na mwin.pl, na grupie facebookowej, gdziekolwiek, gdzie mogą udzielić Ci pomocy. ALE! Zawsze najpierw spróbuj samodzielnie dociec problemu, oraz poszukać odpowiedzi w Googlach. Doświadczeni programiści to zwykle ludzie nerwowi, którzy nie lubią w kółko odpowiadać na to samo pytanie, jeśli odpowiedź jest pierwszym wynikiem w Google, lub autor pytania nie zadał sobie trudu rozwiązania problemu. Jeśli gdzieś pytasz, napisz czego próbowałeś, jakie pomysły zawiodły – to też pomaga dociec problemu. Do tego samodzielne szukanie rozwiązania uczy Cię więcej niż dostanie odpowiedzi na tacy.

Rady radami, ale kluczowe jest doświadczenie. I nie bój się logów! W nich jest niemal wszystko.

Podoba Ci się? Udostępnij!