Criando uma interface de escolha de fases em UNITY
Tags: unity3d, braziliandevs, ui, mobile
Published: 2024-03-10 00:03:30

(Texto ainda em desenvolvimento)

Estou criando um jogo mobile e nele haverá várias fases. É sempre bom ter uma tela que mostra as fases disponíveis e as fases trancadas.

Primeiramente, antes de ir para Unity, geralmente desenho a interface no Figma, mas sinta-se à vontade para usar qualquer outra aplicação semelhante. Então, obtive esse resultado inicial:

![interface de escolha de fase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/apg8nivyfldu6wariuhd.png)

A partir dessa ideia, vamos criar essa interface em Unity e torná-la interativa.

Primeiro, como no Unity não temos objetos de UI como círculos por padrão, irei criar uma imagem com o editor de imagens GIMP:


![circulo basico](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpp9pbvrlqx03yryv9ly.png)

Então, para trazer para o Unity, toda essa parte será feita com o objeto Canvas. Os objetos interativos para selecionar fases serão botões TextMeshPro, as barras serão raw images e o texto será um TextMeshPro padrão.

A estrutura ficou da seguinte forma:


![Estrutura unity](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydkpdqpsap9wizdlypai.png)

E a interface assim:

![Interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mk96gab215rhauysf5j9.png)

interface no simulador

![interface no simulador](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5vno943k3ltl5xk6atnb.png)

A partir dessa interface pronta, é hora de pensar em uma estratégia para quando o usuário apertar o botão da fase escolhida e esse botão passar informações para a cena de jogo. Também por código, mudar o estado de disponibilidade do botão, para só permitir o clique nas fases já desbloqueadas.

---

## Botões

Para fazer os botões funcionarem você pode usar dois objetos

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbus9m5dhsjlbe6kuxn8.png)

Esses objetos ficam com os scripts de mudança de tela e de definir os elementos do nível, nesse caso uso para colocar a skin do enemy.

SceneHandler:

```
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneHandler : MonoBehaviour
{
    public void LoadScene(string nameScene)
    {
        // Carrega a cena com o nome especificado
        SceneManager.LoadScene(nameScene);
    }

    public void ResetScene()
    {
        // Obtém o nome da cena atual
        string nameCurrentScene = SceneManager.GetActiveScene().name;

        // Recarrega a cena atual pelo seu nome
        SceneManager.LoadScene(nameCurrentScene);
    }

    public void Quit()
    {
        Application.Quit();
    }
}
```
Aqui eu uso a função LoadScene para carregar a cena de jogo, passando  o nome dela por parâmetro.

e SetLevel:

```
public class SetLevel : MonoBehaviour
{
    [SerializeField] private List<Sprite> skinsEnemy;
    [SerializeField] private ElementsLevel configLevel;


    public void SetConfig(int num)
    {
        if (skinsEnemy.Count == 0)
        {
            Debug.LogError("Enemy skins list is empty");
            return;
        }

        if (num < 0 || num >= skinsEnemy.Count)
        {
            Debug.LogError("Provided number is out of bounds for the enemy skins list");
            num = 0;
        }

        Sprite currentSkinEnemy = skinsEnemy[num];
        configLevel.skinPaddleNPC = currentSkinEnemy;
        
    }
}
```
Aqui eu inicio uma lista de skins e um [ScriptableObject](https://docs.unity3d.com/Manual/class-ScriptableObject.html) que é a estratégia que estou usando para definir a skin do inimigo.

Em cada botão eu coloco o evento de click da seguinte maneira


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5dw49qwye4h2covv26cp.png)

Escolho a skin que vai ser usada, o número sendo de 0 até o número de skins que tenho até o momento e a cena é a mesma GameOne
 
## Definindo o ScriptableObject

Para definir o scriptableObject faça assim:

```
[CreateAssetMenu(fileName = "ElementsLevel", menuName = "ElementsLevel", order = 1)]
/**
 * <summary>
 * Define game params.
 * </summary>
 */
public class ElementsLevel : ScriptableObject
{
    public Sprite skinPlayer;
    public Sprite skinPaddleNPC;
}

```
Com esse scriptable object eu defino a skin que será usada pelo npc e dentro do nivel eu defino ela no objeto do npc usando um script 'Config Level'.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09u3scll23yudfgg3p2i.png)

```
public class ConfigLevel : MonoBehaviour
{

    [SerializeField] private SpriteRenderer paddleNPC;
    [SerializeField] private ElementsLevel configLevel;

    void Start()
    {
        paddleNPC.sprite = configLevel.skinPaddleNPC;
    }

}

```