Inventář. Část první - grafické rozhraní. Log #13 (Unity, C#)
24.02.2018

      Teď když mám hotové menu, můžu udělat inventář. Bude podobný tomu ve Skyrimu, takže seznam předmětů a okno s popisem předmětu, jen nebude zobrazovat modely předmětů (možná přidám později). Seznam předmětů bude rozdělený podle typů na zbraně, zbroje, nástroje, lektvary (nebo jen byliny, rostliny...? ještě nevím :) ), knihy, zboží a oblíbené. Každý typ bude mít samostatný panel, který bude možné zobrazit nebo skrýt pomocí vrchního panelu v inventáři, kde budou jednotlivé ikony. Ikony těchto typů budou taky mít možnost zvolit oblíbené, pro případ kdy hráč bude chtít zobrazovat jen zbraně a zbroje, po kliknutí prostředním talčítkem myši se označí ikony a po otevření inventáře se budou zobrazovat jen onzačené.

      Pod canvasem UI, kde mám i PlayerMenu vložím nový panel a pojmenuji ho Inventory, pod tímhle panelem bude celý inventář. Nebudu zde popisovat tvorbu těchto panelů, s tím jsem se zabýval v minulém díle. Zaměřím se spíš na uspořádání a layouty prvků v inventáři. V okně inventáře jsou dva hlavní panely, jeden pro tlačítka zobrazených panelů, druhý pro samostatný seznam. Seznam obsahuje panely jednotlivých druhů předmětů a ty už budou obsahovat samostatné stacky - kontejnery pro předměty. Vedle okna seznamu předmětů je pak okno pro popis vybraného předmětu a pod ním tlačítko pro zavření inventáře.

      Abych si zjednodušil uspořádání tlačítek (toggles) pro výběr zobrazeného panelu, použiju tzv. horizontální layout (Horizontal Layout Group). Je to komponenta, která lze přidat na kterýkoliv UI prvek. Umožní vkládání prvků vedle sebe (horizontálně jak název vypovídá) a definovat jejich chování, odstupy, pozici počátečního prvku (nahoře, uprostřed nebo dole a to zleva i zprava) a velikost - Child Controls Size a Child Force Expand. To první určuje jestli výška nebo šířka podřazených prvků je kontrolována layoutem nebo se o to starají prvky samostatně. Druhé pak říká, jestli je potřeba zbytek nevyužitého místa zaplnit podřazenými elementy (opět na výšku i na šířku). Pro můj panel s tlačítky nastavím jen padding 20px z vrchu, 20px mezeru (Spacing) mezi elementy, zarovnání na "Middle center" tedy střed a jen zaškrtnu Heigh ve Force Expand.

      Pro ItemList s panely druhů předmětů aplikuji Vertical Layout Group komponentu. Chová se stejně jen ve vertikálním směru, takže mé panely uspořádá pod sebe, tak jak je mám v inspektoru. Mé panely pro předměty budou mít také Vertical Layout Group komponenty, protože stacky v nich se budou vkládat pod sebe. Jelikož se jedná o seznam a ten se pochopitelně bude zvětšovat s množstvím předmětů a je jasné že celé okno inventáře se zvětšovat nebude, musím to nějak vyřešit. Inventář funguje následovně; každý stack s předmětem (nebo předměty) má svůj kontejner, alias malý panel s ikonou, jménem a počtem předmětů ve stacku, každý nově přidaný stack bude zvětšovat panel svého typu (například panel se zbraněmi) a pokud velikost všech zobrazených panelů přesáhne velikost okna inventáře aktivuje se scrollbar. Takže ten přidám na panel ItemList. Důležité je aby se mi tenhle panel zvětšoval spolu s počtem předmětů. Toho docílím specifickým nastavením výše zmíněných vertical layout komponent. Pro každy panel musím nastavit, mimo spacing a zarovnání na levý vrch, Width pro Child Controls Size. Tím se mi bude zvětšovat panel pokud budu přidávát nové stacky. Stejně tak nastavím i komponentu pro ItemList a k tomu zaškrtnu i Heigh pro stejný pervek. Teď se mi bude panel zvětšovat, ale přesahoval by mi mimo inventář, na to využiji scrollbar. Ten má dvě hlavní časti, samotnou grafiku pro Scrollbar a pak komponentu (ScrollRect). Objekt který má jako podřízený element Scrollbar, musí mít komponentu ScrollRect do které, do políčka Vertical Scrollbar, přetáhnu samotný objekt Scrollbar. Pohraju si s nastavením tak aby mi chování vyhovovalo. Inventáč pak vyapdá následovně.

 

Inventory

 

      Zbývá dodělat zobrazování inventáře po kliknutí na tlačítko v menu a zavření inventáře. Nově vytvořený skript InventoryGUIManager přetáhnu na Inventory. V něm vytvořím funkce ShowInventory() a HideInventory().  V těchto funkcích si do lokální proměnné RectTransform rt vložím komponentu typu RectTransform a budu měnit její lokální pozici.

 

public void ShowInventory()
{
    RectTransform rt = GetComponent<RectTransform>();
    rt.localPosition = new Vector3(rt.localPosition.x, screenHeight / 2 - transform.parent.GetComponent<RectTransform>().localPosition.y, rt.localPosition.z);
}

public void HideInventory()
{
    RectTransform rt = GetComponent<RectTransform>();
    rt.localPosition = new Vector3(rt.localPosition.x, -transform.parent.GetComponent<RectTransform>().localPosition.y * 2, rt.localPosition.z);
}

 

      Pro otevření inventáře v komponentě Button v Inventory_button v PlayerMenu, v panelu On Click() přidám nový event, do prázdného políčka přetáhnu objekt Inventory a vyberu InventoryGUIManager > ShowInventory(). To stejné udělám pro tlačítko zavření inventáře a funkci HideInventory(). Ještě je potřeba aby byl inventář schovaný už při zapnutí hry. Jen přidám metodu Awake() a do ní přidám volání HideInventory(). V dalším díle zprovozním toggles panel.