Unity3d QuickTip – czyli szybkie porady, rozwiązania częstych problemów i sztuczki w Unity3d!
Dzisiejszy odcinek: Jak zrobić pasek życia postaci, oraz automatyczne odnawianie życia
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
Tutaj znów wchodzimy na prostą tematykę. Jaki jest pasek życia postaci każdy widzi. Po co jest? Też chyba wiadomo. Ale żeby nie było za łatwo, omówimy sobie też popularne w dzisiejszych FPSach automatyczne odnawianie życia.
Przygotowanie
Dzisiaj nie potrzebujemy za wiele zabawek, bo po za główną kamerą, będziemy potrzebować tylko tekstury dla paska. Ja zrobiłem sobie prostą teksturę w photoshopie, ale sprawdzi się nawet zamalowany na jednolity kolor prostokąt z painta. U mnie ma wymiary 200×30 pikseli. Do tego dokładamy jeden plik skrytptu, który od razu dodajemy do kamery. (Mój się nazywa healthpoint.cs)
Użyta przeze mnie tekstura jest dostępna do pobrania na samym dole poradnika. Aby odblokować dostęp do downloadu (zasobów i całego projektu) trzeba polajkować/dać +1/Twittnąć wpis.
Wyświetlenie paska zdrowia
Sprawa jest bardzo prosta. Zaczynamy od zmiennych pomocniczych.
private float currentHealth = 100.0f; private float maxHealth = 100.0f; private float canHeal = 0.0f; public Texture2D healthTexture;
Wszystko chyba jest oczywiste? Zapisujemy sobie aktualną oraz maksymalną liczbę punktów życia postaci. Zmienna canHeal, będzie nam sprawdzała, czy już możemy się leczyć. Jak pewnie się orientujesz, w większości gier regeneracja życia nie odbywa się natychmiastowo, a musimy przez jakiś czas pozostać nietrafieni. Ostatnia zmienna przechowuje naszą teksturę. Żeby potem o tym nie zapomnieć, wróć teraz do Unity i dodaj teksturę, przeciągając je na pole tekstury w panelu inspector.
Aby wyświetlić pasek życia, potrzebujemy takiego oto kodu:
void OnGUI() { GUI.DrawTexture(new Rect(10, 10, currentHealth * 100 / maxHealth, 20), healthTexture); }
Pierwszy parametr to oczywiście położenie i wymiar. Przy czym, dla szerokości, nie wpisujemy stałej wartości, a obliczamy długość z proporcji. Ja chciałem by mój pasek życia miał tyle pikseli ile postać może mieć maksymalnie. Jeśli chcesz, żeby maksymalna długość paska była inna, wstaw zamiast wartości maxHealth wybraną przez siebie długość. Oczywiście, najlepiej byłoby ją policzyć uwzględniając rozdzielczość ekranu. Przykładowo może wyglądać to tak:
float hpWidth = Screen.width * 300 / 1024;
Jeżeli dla domyślnej rozdzielczości o szerokości ekranu 1024px chcemy mieć szerokość równą 300px, taki kod załatwi nam sprawę dla innych rozdzielczości. Oczywiście domyślna szerokość powinna być dobrana do Twojej rozdzielczości ekranu, bo wtedy będziesz miał dobry obraz tego, jak gra wygląda. Jeżeli chcesz określić szerokość w procentach, sprawa jest jeszcze łatwiejsza, bo wystarczy szerokość ekranu, pomnożyć przez procent. Przykładowo:
float hpWidth = Screen.width * 0.3f;
Gwarantuje nam pasek o szerokości 30% ekranu, niezależnie od rozdzielczości.
Regeneracja życia
Cały kod, wstawimy sobie w funkcję Update. Po pierwsze, żeby móc testować cokolwiek, potrzebujemy funkcji, która nas zrani.
if(Input.GetButtonDown("Fire1")) { currentHealth -= 10; canHeal = 5.0f; }
Na przyciśnięcie przycisku strzału, tracimy 10 punktów życia i ustawiamy zmienną canHeal na 5. Będzie to nasze 5 sekund, przez które trzeba być nietrafionym. Nie wykorzystałem tutaj podprogramu do odliczania czasu, bo zwykłą zmienną jest łatwiej operować. Zauważ, że jeśli po minięciu 4 sekund, znów zostaniemy trafieni, licznik zwiększy się znów na 5. Kiedy podprogram wstrzyma nam wszystko.
if(canHeal > 0.0f) { canHeal -= Time.deltaTime; }
Kolejny if, sprawdza czy trzeba odliczać czas. Jeśli tak, to zmniejsza go co sekundę. Do póki licznik, nie będzie znów równy zero.
if(canHeal <= 0.0f) { if(currentHealth < maxHealth) { currentHealth += maxHealth * 0.01f; StartCoroutine("heal"); } Mathf.Clamp(currentHealth, 0, maxHealth); }
Sprawdzamy czy canHeal jest mniejsze lub równe zero. Robimy tak ponieważ, w czasie odejmowania czasu, mogliśmy lekko przekroczyć równe zero osiągając np. wartość canHeal = -0.00001. Wtedy sprawdzenie samej równości, nie wychwyci nam tego. Następny ruch to sprawdzenie czy mamy się z czego leczyć, czyli czy obecne punkty życia, są mniejsze od maksymalnych.
Jeżeli wszystko się sprawdziło dodajemy sobie jedną setną punktu życia i odczekujemy pewien czas. Dzięki temu otrzymujemy efekt dynamicznego przyrostu życia, zamiast momentalnego skoku. Tutaj podprogram sprawdza się perfekcyjnie, bo zajmuje mniej kodu, niż gdybyśmy wstawili kolejny timer.
Na samym końcu mamy funkcję Clamp. Pilnuje ona, by zmienna podana jako pierwszy parametr (u nas currentHealth), nie wyszła po zakres wyznaczony przez pozostałe parametry. Działa to tak, że zmienna jest porównywana do obu wartości granicznych i jeśli przekroczyła, którąś o nawet ułamek, jest sprowadzona do wartości granicznej. Zrobiliśmy to, żeby po dodawaniu życia, liczba punktów zdrowia, nie przekroczyła maksymalnego limitu. Można by porównywać na koniec zmiennej currentHealth i maxHealth, ale tak jest bardziej elegancko.
Został nam sam podprogram. Jest on dodatkową funkcją.
IEnumerator heal() { yield return new WaitForSeconds(0.5f); }
Jedyne na co musisz zwrócić uwagę, to fakt, żeby nazwa tej funkcji była taka sama, jak string wewnątrz funkcji startCoroutine. Sama budowa funkcji jest bardzo prosta i przejrzysta. Odczekuje ona tylko wybrany czas. Oczywiście, można było tu wstawić kod dodawania życia, ale użycie funkcji tylko jako odmierzacza czasu, było dla mnie wygodniejsze.
Gotowy Projekt – Download
[to_like]
[/to_like]