Kotlin týden Zimní výprodej
Pouze tento týden sleva až 80 % na e-learning týkající se Kotlin
40 % bodů zdarma díky naší Zimní akci!

Lekce 4 - Unity (C#) Android: Generování stalagů, 2. část

V minulé lekci, Unity (C#) Android: Generování stalagů, jsme si vytvořili kolem mapy pohyblivý tunel, čímž jsme ji ohraničili, a vygenerovali si 50 stalagů. Mapa má však stále ještě rezervy a proto budeme v generování pokračovat i v dnešním Unity 3D Android tutoriálu.

Různá výška překážek

Aby všechny překážky nebyly stejně velké, upravíme si metodu GenerateStalag() v našem StartScript do následující podoby:

void GenerateStalag(Vector2 p)
{
    GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject;
    Vector3 scale = g.transform.localScale;

    scale.y = Random.Range(0.5f, 1.2f);

    g.transform.localScale = scale;
}

Za vysvětlení stojí řádek:

GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject;

Kód funguje stejně jako předtím, jen s menším rozdílem. Náš vytvořený objekt se nám uloží do proměnné. S touto proměnnou následně můžeme pracovat a upravit libovolné vlastnosti nového objektu.

Vytvoříme si plně vybarvené okraje naší obrazovky, abychom tam neměli takovou díru. Výplň si přesuneme do objektu Borders1 a uložíme.

V Prefabu našeho stalagu si změníme Order in Layer na -1 a potvrdíme. To zajistí, aby se nám nepřekrýval s jinými sprity.

Aby naše hra byla lépe optimalizovaná, Prefabu našeho krápníku vytvoříme vlastní vrstvu. Pojmenujeme si ji StalagLayer a to samé uděláme s Prefabem zdi, které vytvoříme vrstvu BorderLayer:

Dále v Edit -> Project settings -> Physics2D nastavíme, aby spolu StalagLayer a BorderLayer nekolidovaly. To děláme proto, že na obou objektech máme collider a kdyby spolu tyto objekty neustále kolidovaly, mohla by se tím razantně zvýšit náročnost naší hry, která by se mohla následně sekat:

Stalagy ze země

Zatím nám překážka visí pouze ze stropu, zařídíme, aby trčela i ze země. To provedeme další změnou skriptu StartScript:

void Start()
{
    for (int i = 0; i < count; i++)
    {
        Vector2 pos = new Vector2();
        pos.x = offset + i * distance;

        int r = Random.Range(0, 2);
        int rotateIndicator = 1;
        if (r == 0)
        {
            pos.y = 4.5f; // může se lišit podle toho. jak máte vzdálený strop a podlahu od sebe
        }
        else
        {
            pos.y = -4.5f; // může lišit podle toho, jak máte vzdálený strop a podlahu od sebe
            rotateIndicator = -1;
        }

        GenerateStalag(pos, rotateIndicator);
    }
}

void GenerateStalag(Vector2 p, int rotateInd)
{
     GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject;
     Vector3 scale = g.transform.localScale;

     scale.y = Random.Range(0.5f, 1.2f)  *rotateInd;
     g.transform.localScale = scale;
}
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Když hru spustíme, můžeme vidět, že se nám stalagy náhodně otočily.

Optimalizace

Dále si hru trochu optimalizujeme. Teď generujeme všechny stalagy najednou, jenže to může být docela zbytečné. Tudíž jich budeme vždy generovat jen pár.

Na náš StartingObject si přidáme Box collider a odškrtneme, že se jedná o trigger. Zvětšíme a posuneme ho tak, aby byl na výšku přes celou naší hrací plochu a zároveň byl alespoň trochu široký. Následně ho přesuneme před hráče. Dále hráči přidáme tag Player a upravíme si náš skript:

public GameObject stalagPrefab;
public float distance = 10;
public float offset = 10;
public int count = 50;

public Vector3 lastPos;

void Start()
{
    lastPos = transform.position;
    //GenerateSet(); // již nepotřebujeme ve startu
}

void GenerateSet()
{
    for (int i = 0; i < count; i++)
    {
        Vector2 pos = new Vector2();
        pos.x = lastPos.x + (2*distance) +  offset + i * distance;

        int r = Random.Range(0, 2);
        int rotateIndicator = 1;
        if (r == 0)
        {
            pos.y = 4.5f; // toto číslo se může lišit podle toho, jak máte vzdálený strop a podlahu od sebe
        }
        else
        {
            pos.y = -4.5f; // toto číslo se může lišit podle toho, jak máte vzdálený strop a podlahu od sebe
            rotateIndicator = -1;
        }

        GenerateStalag(pos, rotateIndicator);
    }
}

void GenerateStalag(Vector2 p, int rotateInd)
{
    GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject;
    Vector3 scale = g.transform.localScale;


    scale.y = Random.Range(0.5f, 1.2f)  *rotateInd;

    g.transform.localScale = scale;
}

// vždy, když náš objekt proletí colliderem tohoto objektu, vygenerují se nové překážky a následně se náš celý objekt posune
void OnTriggerEnter2D(Collider2D col)
{
    if (col.CompareTag("Player"))
    {
        GenerateSet();
        lastPos = transform.position;
        lastPos.x += count * distance;
        transform.position = lastPos;
    }
}

Dále zajistíme, aby se naše překážky generovaly na správných místech. Stačí pouze lehce upravit naší metodu na generování:

void GenerateStalag(Vector2 p, int rotateInd)
{
    GameObject g = Instantiate(stalagPrefab, p, Quaternion.identity) as GameObject;
    Vector3 scale = g.transform.localScale;

    scale.y = Random.Range(0.5f, 1.2f)  *rotateInd;

    g.transform.localScale = scale;

    Bounds bound = g.GetComponent<SpriteRenderer>().bounds;
    p.y -= bound.size.y / 2 * rotateInd;

    g.transform.position = p;
}

Bounds jsou hranice (velikost) objektu. Vzali jsme si tedy velikost našeho spritu na stalagmit a vypočítali jsme díky tomu jejich umístění.

Když hru spustíme, můžeme vidět, že už vypadá pěkně.

Náhodná šířka a více druhů stalagů

Hráče může omrzet, když uvidí pouze jednu a tu samou překážku stále dokola, jen jinak velkou. Přidáme tedy i náhodnou šířku stalagů a dále i více druhů.

Více druhů stalagů

Abychom generovali více druhů stalagů, potřebujeme si vytvořit pole našich překážek:

public GameObject[] stalagPrefab;

Z naší proměnné pro Prefab vytvoříme pole. A následně musíme upravit ještě část kódu na generování:

GameObject g = Instantiate(stalagPrefab[Random.Range(0, stalagPrefab.Length)], p, Quaternion.identity) as GameObject;

Random.Range(0, stalagPrefab.Length) nám zajistí vygenerování stalagmitu na náhodném indexu z celé délky pole našich stalagmitů.

Teď, když se podíváme do Inspectoru na náš StartingObject, můžeme tam vidět možnost zvolit velikost našeho pole. My zvolíme 4.

Můžete použít sprity, které jsem vám dal ke stažení a nebo si můžete vytvořit vlastní.

Následně uděláme to samé jako s prvním stalagem. Nastavíme barvu, collider, order in layer, Layer a uložíme jako Prefab. Následně tento Prefab dáme do našeho pole.

Když hru spustíme, můžeme vidět, že se generují různé druhy.

Takto si můžeme vytvořit libovolný počet různých stalagů. Pokud nám budou přidat velké a nebo malé, můžeme si velikost generování libovolně upravit.

Pro lepší přehlednost si vytvoříme další proměnné:

public float minHeight;
public float maxHeight;
public float minWidth;
public float maxWidth;

Ve finále si upravíme naší metodu na generování, aby se náhodně určovala i šířka stalagů:

scale.y = Random.Range(minHeight, maxHeight)  *rotateInd;
scale.x = Random.Range(minWidth, maxWidth);

Od teď můžeme pohodlně z Inspectoru měnit naše hodnoty a nemusíme pracně hledat v kódu.

Závěr

Pro dnešek to bude vše. Doufám, že se vám série tutoriálů líbí a naučili jste se něco nového. Pokud máte nějaké připomínky či nápady, zanechte komentář, rád se inspiruji. Příště se v lekci Unity (C#) Android: Nastavení prostředí podíváme na vytvoření menu.


 

Stáhnout

Staženo 12x (92.84 kB)

 

 

Aktivity (2)

 

 

Komentáře

Avatar
Roman Souček:18. února 14:04

Ahoj, měl jsem menší problem, který jsem po nějaké době vyřešil. Když jsem vytvářel pole pro generování čtyřech různých stalagu, je tam kód, ... stalagPrefab.... ale mě to fungovalo jen když jsem zadal ...stalagPrefabs... to samé pak při úpravě kódu pro generování... jinak super tutor... mam knihu, kterou se učím C# ale je to hodně teoretické a nebo spíš nepraktické. S kombinací s timhle tutorialem mi vše dochází a je fajn, že mi dvou měsíční učení konečně přináší ovoce :)...

 
Odpovědět
18. února 14:04
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Jan Kubice
Redaktor
Avatar
Odpovídá na Roman Souček
Jan Kubice:0:17

Ahoj, jsem rád že se tutoriál líbí :-) Kouknu se kde je chyba a kdyžtak opravím. Je možné, že jsem někde něco špatně opsal do tutoriálu. Děkuji za upozornění a doufám, že se těšíš na další díly :-)

 
Odpovědět
0:17
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.