Unity3d QuickTip – czyli szybkie porady, rozwiązania częstych problemów i sztuczki w Unity3d!
Dzisiejszy odcinek: Jak zrobić strzelanie? Funkcja Instantinate.
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
#303030;">Teoria
Dziś, omówimy sobie jak zrobić proste strzelanie pociskami. Oczywiście są dwa sposoby wykonania strzelania. W jednym z nich, stosujemy RayCasting – będzie to sposób znany z gier typu Call Of Duty, gdzie strzelamy z nowoczesnej broni palnej i kula leci zbyt szybko, by można było ją dostrzec. W drugiej metodzie – którą my sobie zastosujemy – tworzymy prefabrykant pocisku i korzystamy z funkcji Instantinate. Jest to metoda nieco bardziej zasosobożerna, ale znajduje zastosowanie w większej ilości gier. Omawiana metoda, znajdzie zastosowanie w grach platformowych – Mario na 3 poziomie, shoot em up – Tyrian, czy nawet dla niektórych broni w strzelankach – granatnik/rakietnica w Quake 3 Arena.
Przygotowanie
Pierwszym krokiem, będzie oczywiście stworzenie sobie miejsca na testy. U mnie był to prosty sześcian (rozmiar x i z zmieniony na 100) na którym będą stały wszystkie obiekty. Do wykonania reszty, posłuży nam zaimportowany ze standardowych assetów First Person Controller (Paczka: Character Controller).
Teraz zostaje nam zrobić prefabrykant pocisku. U mnie będzie to zwykła sfera, w kolorze niebieskim. Dlatego zaczynam od stworzenia obiektu sfery [GameObject -> Create Other -> Sphere]. Teraz nadamy mu kolor:
W panelu Project klikamy prawym i wybieramy [Create -> Material]. Zaznaczamy nowo powstały materiał. W panelu inspector wybieramy kolor w polu Main Color. Teraz dodajemy materiał do utworzonej wcześniej sfery. Można to zrobić przenosząc po prostu materiał na nazwę sfery w panelu hierarchy.
Aby pocisk zachowywał się prawidłowo, musimy dodać mu komponent bryły sztywnej (Rigidbody). Można to zrobić np. przez zaznaczenie pocisku, po czym wybierając z menu górnego: [Component – >Physics -> Rigidbody]. Nie musimy zmieniać jego parametrów.
Teraz zostaje pytanie jak ze sfery zrobić prefabrykant. Jest to bardzo proste: Wybieramy naszą sferę w panelu hierarchy i przeciągamy ją do panelu project. Jeśli zrobiłeś to poprawnie, zobaczysz, że w panelu hierarchy nazwa sfery zmieniła kolor z szarego na niebieski. Możesz teraz spokojnie usunąć obiekt Sphere z panelu Hierarchy, a tym samym ze sceny.
Strzelamy – Instantinate
Aby zrobić samo strzelanie, musimy stworzyć nowy skrypt, który przypisujemy od razu do obiektu Main Camera, będącego składową First Person Controllera. Aby zobaczyć obiekt kamery, kliknij na strzałkę przy obiekcie First Person Controller w panelu hierarchy. Ja skrypt nazwałem shoot.cs i przeciągnąłem go na obiekt gracza.
Zaczynamy od tego, że potrzebujemy wiedzieć, jak wygląda nasz pocisk. Dlatego tworzymy sobie zmienną publiczną, typu Rigidbody.
public Rigidbody bullet;
[stextbox id=”info” defcaption=”true”]Tak naprawdę, mógłby być tutaj obiekt typu GameObject, jednak ustawienie typu Rigidbody, wymusza, by przypisany tutaj obiekt, posiadał ten komponent.[/stextbox]
Teraz możemy na chwilę wrócić do Unity. Zaznaczmy First Person Controller. Widzimy, że w panelu Inspektor, przy skrypcie pojawiła się zmienna, wymagająca GameObjectu. Wybieramy naszą Sferę z panelu Project i przeciągamy ją w to miejsce i wracamy do MonoDevelop.
Teraz czas na zrobienie wystrzeliwania pocisku. Posłuży do tego taki prosty kawałek kodu:
void Update () { if(Input.GetButtonDown("Fire1")) { Rigidbody clone = Instantiate(bullet, transform.position, transform.rotation) as Rigidbody; Vector3 fwd = transform.TransformDirection(Vector3.forward); clone.AddForce(fwd * 1500f); } }
Wszystko wstawiamy do funkcji Update, bo chcemy, żeby strzelać się dało w każdej chwili. Sprawdzamy czy naciśnięty został przycisk oznaczony jako Fire1 – domyślnie jest to lewy ctrl lub lewy klawisz myszy. Warunek sprawdza czy przycisk został naciśnięty, a nie wciśnięty, więc wykonujemy wystrzał pojedynczy.
[stextbox id=”info” defcaption=”true”]Jeżeli chcielibyśmy otrzymać ogień ciągły, jak np. z karabinu, powinniśmy zastosować funkcję GetButton. Jednak wtedy należy użyć jakiegoś timera kontrolującego wystrzał, gdyż bez tego, pocisk wylatywałby w każdej klatce gry.[/stextbox]
Kolejna linijka, tworzy instancję obiektu pocisku. Funkcja Instantinate przyjmuje parametry: prefabrykant, nasze zadeklarowane wcześniej bullet, oraz pozycję i rotację z jaką obiekt ma się utworzyć. Z racji że chcemy strzelać przed siebie, podajemy pozycję i rotację obiektu w którym skrypt się znajduje. I tutaj też, rozwiązuje się zagadka, czemu skrypt przypisaliśmy do kamery. Oczywiście dlatego, że kamerą swobodnie się obracamy i sprawiamy, że pocisk zawsze poleci tam gdzie patrzymy. Gdybyśmy przypisali skrypt do obiektu First Person Controller, pociski byłby wystrzeliwane w bliżej nieokreślonym kierunku.
Następny krok to stworzenie sobie wektora przesunięcia skierowanego do przodu. Będzie to nam potrzebne w kolejnej linii.
Funkcja AddForce przekazuje obiektowi energię. Można sobie to wyobrazić, jak pchnięcie obiektu w stronę jaką wskazuje wektor (bo funkcja przyjmuje jako parametr wektor). My utworzyliśmy sobie wektor wskazujący przód. Mnożymy go przez 1500 by otrzymać mocniejszy wystrzał.
[stextbox id=”info” defcaption=”true”]Możemy pomnożyć wektor przez liczbę. Jeśli założymy że nasza postać spogląda w kierunku V3(1, 0, 0), to efekt mnożenia i funkcji AddForce sprawi, że pocisk zostanie wystrzelony w zgodzie z wektorem V3(1500, 0, 0).[/stextbox]
Możesz teraz wrócić do Unity i przetestować kod.
Sprzątamy po sobie
Stworzenie masy obiektów typu Rigidbody nie wpływa pozytywnie na wydajność gry. Dlatego wypadałoby posprzątać i po pewnym czasie usunąć niechciane pociski. Dlatego wracamy do Unity i tworzymy nowy skrypt. U mnie jest to: Bullet.cs. Skrypt przypisujemy do prefabrykantu pocisku. Wystarczy skrypt przeciągnąć na prefabrykant w panelu Project.
Teraz przechodzimy do edycji skryptu.
Jedyne co zrobimy, to prosty licznik, który po pewnym czasie usunie obiekt. Zaczniemy od deklaracji zmiennej:
private float timer = 0.0f;
Jest to prosta zmienna typu float, która będzie odliczała czas. Prywatna bo nie chcemy by ktoś w niej zmieniał wartość. Reszta kodu jest równie prosta:
void Update() { timer += Time.deltaTime; if(timer > 4.0f) { Destroy(gameObject); } }
Wewnątrz funkcji update do zmiennej timer, dodajemy po 1 sekundzie niezależnej od klatek, co zapewnia nam Time.deltaTime. Następnie sprawdzamy czy nasz odliczany czas przekroczył 4 sekundy.
[stextbox id=”info” defcaption=”true”]W profesjonalnym kodzie, zaleca się używania zmiennej, zamiast sztywnej liczby. Tutaj pozwoliłem sobie na taki zapis, ze względu na chęć skrócenia kodu do minimum.[/stextbox]
Jeśli czas upłynął, niszczymy obiekt, w którym znajduje się skrypt. Dla nas, będzie to każdy klon pocisku.
[stextbox id=”info” defcaption=”true”]Warto zwrócić uwagę na różnicę między GameObject, a gameObject. Pierwsze to ogólna klasa, którym są wszystkie elementy w świecie Unity. Za to gameObject, to odowłanie się w skrypcie do obiektu, w którym skrypt się znajduje.[/stextbox]
Zostało uruchomić grę i sprawdzić działanie skryptu. Warto tutaj obserwować panel Hierachy, gdzie zobaczysz jak nowy obiekt pojawia się, po czym znika po pewnym czasie.
Download – Kompletny projekt
[to_like]
[/to_like]