NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Lekce 11 - Unity (C#) Android: Start, Skóre, PlayerPrefs

V minulé lekci, Unity (C#) Android: Přestavba, bodáky, jsme upravili pohyb hráče a pozměnili i způsob, jakým se nám posouvají překážky.

Dnes se podíváme na počítání skóre a také na počkání na startu, dokud hráč neklepne, aby měl čas se na hru plně připravit.

Vyčkání na start

Začneme s vyčkáním, dokud hráč nezačne hrát. Pro tento účel upravíme skript pro pohyb hráče. Prvně ale objektu Player nastavíme gravitaci na 0, aby nám při čekání nepadal. Ideálně si číslo, které jste měli nastavené předtím, někam poznamenejte.

Nyní si otevřeme PlayerMoveScript.

Do našeho skriptu si přidáme na úplný začátek novou proměnnou:

bool started = false;

A do Update() metody vložíme následující kód:

if (!started)
{
    return;
}

Když hru spustíme, hráč nám stojí na místě a nehýbe se. To je přesně to, co jsme chtěli. Ovšem v tento moment chceme čekat, dokud hráč nezačne hrát. Předtím, než budeme reagovat na nějakou tu akci, si vytvoříme metodu v tom samém skriptu. Metoda se bude jmenovat StartGame():

void StartGame()
{
    started = true;
    rigidbody2D.gravityScale = 1f; // Vaše hodnota, např. 1f

    Vector3 vel = rigidbody2D.velocity;
    vel = Flap(vel);

    rigidbody2D.velocity = vel;
}

Metoda nám při jejím zavolání nastaví started na true. Také nastaví gravitaci na původní číslo, které jsme měli nastavené na hráčovi (to si v kódu upravte).

Když hráč klikne, začne padat a musel by rychle klepnout znovu. Proto jsme zařídili, aby nám postavička zároveň i "flapla" a tím hráč dostane chvíli času na zareagování. Pou­žíváme k tomu metodu Flap(), kterou si hned také přidáme.

Kód metody Flap() je následující:

Vector3 Flap(Vector3 v)
{
        v.y = flapAmount;
        return v;
}

Nyní upravíme část pod podmínkou !started do této podoby:

if (!started)
{
    if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
    {
        StartGame();
    }

    return;
}

Kdyby se někomu nepovedlo poskládat metody do skriptu, níže je pro kontrolu jeho finální podoba:

float flapAmount = 7;
float speed = 5;
bool started = false;

void Start()
{

}

// Update is called once per frame
void Update()
{

    if (!started)
    {
        if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
        {
            StartGame();
        }

        return;
    }


    Vector3 vel = gameObject.GetComponent<Rigidbody2D>().velocity;

    if (Input.GetMouseButtonDown(0))
    {
        vel = Flap(vel);
    }

    vel.x = speed;

    gameObject.GetComponent<Rigidbody2D>().velocity = vel;

}

void StartGame()
{
    started = true;
    GetComponent<Rigidbody2D>().gravityScale = 1f;

    Vector3 vel = GetComponent<Rigidbody2D>().velocity;
    vel = Flap(vel);

    GetComponent<Rigidbody2D>().velocity = vel;
}

Vector3 Flap(Vector3 v)
{
    v.y = flapAmount;
    return v;
}

Není tu asi nic, co bychom museli speciálně vysvětlovat. Vše v tomto kódu již v tutoriálu zaznělo, tak se můžeme vrhnout na další část.

Počítání skóre

Nyní začneme s počítáním skóre. Na náš stalag přidáme další objekt, který bude zjišťovat, zda hráč proletěl. Všem prefabům stalagu přidáme objekt. Vytvoříme si prázdný gameObject, vynulujeme jeho souřadnice a pojmenujeme ho například stalagScore. Tento objekt vložíme jako podobjekt stalagu. Přidáme mu Box Collider2D.

Collider si zvětšíme po ose Y dostatečně daleko a pokusíme se collider narovnat se spodkem stalagu. Nebo ho také můžeme dát více do středu, co se vám více líbí, na funkcionalitu to vliv mít nebude. Nebojte se to vážně roztáhnout klidně na desetinásobek velikosti stalagu. Mohlo by se stát, že tento collider bude moc malinký kvůli našem generování stalagů v náhodných velikostech a hráč se ho třeba ani nedotkne a nepřičte se mu skóre. Také musíme tento collider nastavit jako trigger:

Tvorba 2D arkády pro Android v Unity

Dále tomuto objektu přidáme ScoreScript. Tento skript bude, jak asi tušíte, přičítat skóre. Pro tyto účely si přidáme Text na obrazovku jako GameObject -> UI -> Text.

Vytvoří se nám samozřejmě také Canvas, ale s tím již umíme pracovat z minulých lekcí. Tudíž si ho nastavíme na kameru, aby byl stále pěkně vidět. Tento text nám bude vypisovat aktuální skóre. Text si umístíme do pravého horního rohu, zvětšíme si font a text nastavíme například jen na Score: 0. Tomuto textu přidáme TextScoreScript.

Základ máme připraven.

Skripty

Vrhneme se na ony dva skripty.

TextScoreScript

Nejdříve upravíme náš TextScoreScript:

static int score = 0;

void Start ()
{
    score = 0;
}

public static void AddScore()
{
    score++;
}

Programátoři určitě tuší, proč před score máme static int. Neprogramátoři asi moc neví. Když máme nějakou statickou proměnnou nebo metodu, jsme schopní k ní přistupovat i z různých metod a tříd, aniž bychom ji museli nějak získávat. Taková metoda ovšem ale může pracovat zas jen se statickými proměnnými ve třídě. Díky tomu, že metodu máme statickou, jsme schopni udělat další skript jednodušší.

ScoreScript

Když přes náš trigger přeletí hráč, chceme přičíst skóre. To uděláme zavoláním metody na třídě TextScore:

void OnTriggerEnter2D(Collider2D col)
{
    if(col.CompareTag("Player"))
    {
        print("Adding score");
        TextScore.AddScore();
    }
}

Díky tomu, že v dané třídě máme metodu statickou, jsme schopni k ní přistoupit, aniž bychom dělali něco takového:

GameObject.Find("název objektu").SendMessage...

Nebo ještě hůře takového:

GameObject.Find("název objektu").getComponent...

Hůře proto, že je to zbytečně složité, jak pro nás, tak pro počítač. Představte si scénu, kde máte tisíce objektů a počítač mezi nimi musí najít daný objekt, na objektu najít skript a až potom jsme tam, kde chceme být.

Nyní, když hráč proletí úspěšně kolem stalagu, vnitřně se nám skóre přičte, ale nikde jej nevidíme.

TextScoreScript

Proto se vrátíme zpět do TextScoreScript, kde zavedeme novou proměnnou. Pokud hráč zdolá překážku, tuto proměnnou si nastavíme na true a změníme text, který ukazuje aktuální body:

static int score = 0;
static bool changed = false;

void Start ()
{
    score = 0;
}

void Update ()
{

    if(changed)
    {
        changed = false;
        gameObject.GetComponent<Text>().text = "Score: " + score;
    }

}

public static void AddScore()
{
    score++;
    changed = true;
}

Při aktualizování textu se vždy odkážeme na aktuální objekt, kde se nachází náš text na vypisování skóre, a zároveň náš skript.

Přičítání skóre je hotové a my se můžeme vrhnout na ukládání nejlepšího skóre.

Nejlepší skóre

Přidáme si nový text, který si dáme menší než ten původní, a pojmenujeme si ho GUIHighScore. Dáme text pod naše aktuální skóre. Také mu můžeme přidat text "HighScore: ".

Tvorba 2D arkády pro Android v Unity

Tomuto textu přidáme nový skript HighScore. Nejdříve se ale vrátíme k našemu ScoreScript.

ScoreScript

Přidáme si do něj jednu metodu:

void OnDestroy()
{
    int highscore = PlayerPrefs.GetInt("highscore", 0);

    if (score > highscore)
        PlayerPrefs.SetInt("highscore", score);
}

Tato metoda je v Unity již předpřipravená podobně, jako jsou metody Start() nebo Update(). Tato metoda se volá vždy při zničení objektu nebo při ukončení scény.

PlayerPrefs

Dále tu máme PlayerPrefs. To je třída s užitečnými metodami pro ukládání velmi jednoduchých dat.

Načítání

Data hráče načteme takto:

PlayerPrefs.GetInt("highscore", 0);

Načteme hodnotu, která je uložena pod klíčem "highscore". Pokud daná hodnota nebude nalezena, vrátí se nám 0. Kdybychom jako druhý parametr zadali například 5, tak budeme mít v highscore hodnotu 5, pokud se žádné uložené skóre nenajde.

Ukládání

Metoda SetInt() dělá přesný opak:

PlayerPrefs.SetInt("highscore", score);

Ukládáme pod klíč "highscore" číslo, které se nachází v proměnné score:

Takže pokud hráč dosáhne skóre většího, než je uložené v PlayerPrefs, tak se zapíše do paměti.

Pokud by vás zajímalo, kam se například na Windows tyto hodnoty ukládají, můžete je najít uložené v registrech. Samozřejmě je tam najdete až alespoň po jednom odehrání hry. Pro nezkušené doporučuji se v registrech počítače moc nehrabat, můžete si nepříjemně poškodit soubory a funkčnost aplikací.

Pro účely testování hry si můžeme přidat na první řádku metody OnDestroy() vymazání skóre:

PlayerPrefs.DeleteKey("highscore");

To zajistí, abychom zbytečně nenahráli veliké skóre na našem počítači. Až hru budeme mít hotovou, nezapomeňme tuto řádku samozřejmě smazat.

Ještě jedna možnost je ta, že si můžeme přidat podmínku:

If (Application.isEditor)
    PlayerPrefs.DeleteKey("highscore");

Takže dokud nebudeme mít hru vydanou a budeme ji spouštět pouze přes Unity, tak se pokaždé vymaže skóre.

HighScore skript

Nyní se přesuneme do HighScore skriptu:

void Start ()
{
    int highscore = PlayerPrefs.GetInt("highscore", 0);
    gameObject.GetComponent<Text>().text = "Highscore: " + highscore;
}

Takže pokaždé, když hru spustíme, se nám aktualizuje text obsahující highscore na nejvyšší nahrané skóre.

V příští lekci, Unity (C#) Android: Vylepšení pohybu nakláněním, uděláme drobnou opravu sekání a dále vylepšíme pohyb postavy hráče.


 

Předchozí článek
Unity (C#) Android: Přestavba, bodáky
Všechny články v sekci
Tvorba 2D arkády pro Android v Unity
Přeskočit článek
(nedoporučujeme)
Unity (C#) Android: Vylepšení pohybu nakláněním
Článek pro vás napsal Jan Kubice
Avatar
Uživatelské hodnocení:
1 hlasů
Aktivity