Sistema de coletar itens para aumentar vida/magia


To implementando algumas mecânicas pra um possível jogo e gostaria de saber como eu implemento um sistema que ao coletar um determinado número do mesmo item, aumente a barra de vida/magia?
Seria parecido com o sistema de coletar moedas?

1 curtida

Cria uma variável pra armazenar a quantidade de itens coletados, uma variável pra vida do personagem e um método pra aumentar a quantidade de vida toda vez que a quantidade de itens coletados alcançar o valor determinado, é bem simples na verdade, da pra fazer algo mais elaborado dependendo do que tu quer

Eu tentei fazer aqui, mas acho que não é desse jeito.
Eu tenho que referenciar a barra de vida?


O script de vida:

A barra de vida:

1 curtida

using UnityEngine;
using UnityEngine.UI;

public class BarraDeVida : MonoBehaviour
{
//Colocar esse script no player

public Slider barraDeVida; //Arrastar o slider pra cá
public int vidaMaxima;
public int vidaAtual;
public int itensColetados;

private void Start()
{
    //Como eu to lidando apenas com valores inteiros eu converti pra int
    //Mas o melhor deveria ser usar float, porque max value e value são float
    vidaMaxima = (int)barraDeVida.maxValue;
    vidaAtual = (int)barraDeVida.value;
}

//Método pra mudar o tamnho do slider, pode ser usado valores personalizados
//Se não quiser que ele mude é só não chamar no método AtualizarVida
public void MudarTamanhoDoSlider(int altura,int largura)
{
    RectTransform rectTransform = barraDeVida.GetComponent<RectTransform>();
    rectTransform.sizeDelta = new Vector2(altura, largura);
}


public int AtualizarVidaMaxima(int vidaMaxima)
{
   //toda vez que esse método for chamado ele vai atualizar a vida maxima
   //e a vida atual do player
    barraDeVida.maxValue = vidaMaxima;
    barraDeVida.value = vidaMaxima;//Se quiser que a vida atual não seja atualizada é só remover essa linha
    return this.vidaMaxima = vidaMaxima;
}

public void AumentarItensColetados()
{
    itensColetados++;
}


public void AtualizarVida()
{
    //Aqui ele vai atualizar tanto o valor do slider, quanto da vida máxima
    //como essa condição não está sendo chamada no update, deve ser colocado o valor desejado -1;
    if(itensColetados >= 4)//apesar de ser 4, ela vai atualizar quando chegar a 5
    {
        AtualizarVidaMaxima(110);
        MudarTamanhoDoSlider(1000,160);
        vidaMaxima = (int)barraDeVida.maxValue;
        vidaAtual = (int)barraDeVida.value;
    }
}


private void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.collider.gameObject.CompareTag("Coletavel"))
    {
        AtualizarVida();
        AumentarItensColetados();

    }
}

}


Só tem que ajustar o valor de Max Value e Value no slider, que as váriaveis vidaMaxima e vidaAtual vão se ajustar ao começar o jogo. E uma coisa que eu esqueci de fazer é colocar pra destruir o objeto toda vez que houver colisão

Então a barra tem que ser em formato de slider? Porque a que eu peguei ja tava pronta, mas beleza eu sei como faz desse tipo. Muito obrigado

1 curtida

Eu vi a barra e achei que ela era um slider na verdade, mas ai é só mudar os sprites do slider que ela fica igual, fica bem mais fácil.

No caso eu tenho que criar painéis pra cada vez que pegar o item(pra 1,2,3 e 4) e colocar um botão de continuar.

1 curtida

using UnityEngine;
using UnityEngine.UI;

public class BarraDeVida : MonoBehaviour
{
//Colocar esse script no player

[SerializeField] private GameObject panelItens;//arrastar o painel aqui

public Slider barraDeVida; //Arrastar o slider pra cá
public int vidaMaxima;
public int vidaAtual;
public int itensColetados;


private void Start()
{
    //Como eu to lidando apenas com valores inteiros eu converti pra int
    //Mas o melhor deveria ser usar float, porque max value e value são float
    vidaMaxima = (int)barraDeVida.maxValue;
    vidaAtual = (int)barraDeVida.value;
}

//Método pra mudar o tamnho do slider, pode ser usado valores personalizados
//Se não quiser que ele mude é só não chamar no método AtualizarVida
public void MudarTamanhoDoSlider(int altura, int largura)
{
    RectTransform rectTransform = barraDeVida.GetComponent<RectTransform>();
    rectTransform.sizeDelta = new Vector2(altura, largura);
}


public int AtualizarVidaMaxima(int vidaMaxima)
{
    //toda vez que esse método for chamado ele vai atualizar a vida maxima
    //e a vida atual do player
    barraDeVida.maxValue = vidaMaxima;
    barraDeVida.value = vidaMaxima;//Se quiser que a vida atual não seja atualizada é só remover essa linha
    return this.vidaMaxima = vidaMaxima;
}

public void AumentarItensColetados()
{
    panelItens.SetActive(true);//Mostrar painel na tela toda vez que o item for coletado
    itensColetados++;
    Time.timeScale = 0;//o jogo vai ser parado quando o painel estiver ativo,
    //pode remover essa linha se quiser que o jogo conntinue
    
}

//Método pra ser chamado no evento de OnClick do botão
public void FecharPainel()
{
    panelItens.SetActive(false);//Mostrar painel na tela toda vez que o item for coletado
    Time.timeScale = 1;//Despausar o jogo
}


public void AtualizarVida()
{
    //Aqui ele vai atualizar tanto o valor do slider, quanto da vida máxima
    //como essa condição não está sendo chamada no update, deve ser colocado o valor desejado -1;
    if (itensColetados >= 4)//apesar de ser 4, ela vai atualizar quando chegar a 5
    {
        AtualizarVidaMaxima(110);
        MudarTamanhoDoSlider(1000, 160);
        vidaMaxima = (int)barraDeVida.maxValue;
        vidaAtual = (int)barraDeVida.value;
    }
}


private void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.collider.gameObject.CompareTag("Coletavel"))
    {
        AtualizarVida();
        AumentarItensColetados();

    }
}

}

Ai o script atualizado pra abrir o painel toda vez que ele pegar o item, só tem que criar o painel e o botão,
deixar ele desativado na cena. Também adicionei o método pra continuar o jogo quando clicar no botão de continuar, o método tem que ser chamado no evento de OnClick do botão.

Da pra adicionar várias coisas no painel, toda vez que adicionar um coletável por exemplo, é só ir fazendo algumas alterações no script conforme o que tu quer.

No caso pra 4 paineis diferentes(com 1 , com 2, com 3 e 4) é só copiar no script essa parte?

public void AumentarItensColetados()
{
panelItens.SetActive(true);//Mostrar painel na tela toda vez que o item for coletado
itensColetados++;
Time.timeScale = 0;//o jogo vai ser parado quando o painel estiver ativo,
//pode remover essa linha se quiser que o jogo conntinue

}

//Método pra ser chamado no evento de OnClick do botão
public void FecharPainel()
{
panelItens.SetActive(false);//Mostrar painel na tela toda vez que o item for coletado
Time.timeScale = 1;//Despausar o jogo
}

1 curtida

Acho melhor copiar o script todo e substituir o antigo, ele só vai adicionar algumas coisas novas. Não precisa criar 4 painéis diferentes, basta ir fazendo alguns ajustes no painel a cada vez que o item coletado aumentar, da pra fazer várias coisas, e só me dizer qual a diferença de um painel pra outro.

O que muda é o numero de “pedaços de vida” que coletar(1,2,3 e 4)
E o desenho vai mudando no painel
1pedacoColetado
2pedacoColetado
3pedacoColetado
4pedacoColetado

1 curtida

using UnityEngine;
using UnityEngine.UI;

public class BarraDeVida : MonoBehaviour
{
//Colocar esse script no player

[SerializeField] private Image ImagemJogo; // Aqui vai a imagem criada no canvas
[SerializeField] private Sprite sprites; // Mover as 4 imagens aqui
[SerializeField] private GameObject panelItens;//arrastar o painel aqui

private int indiceImagemAtual = 0;//ImagemAtual



public Slider barraDeVida; //Arrastar o slider pra cá
public int vidaMaxima;
public int vidaAtual;
public int itensColetados;


private void Start()
{
    //Como eu to lidando apenas com valores inteiros eu converti pra int
    //Mas o melhor deveria ser usar float, porque max value e value são float
    vidaMaxima = (int)barraDeVida.maxValue;
    vidaAtual = (int)barraDeVida.value;
}

//Como eu não adicionei nenhum sprite a imagem no canvas,eu fiz uma condição pra ela sempre 
//começar pelo indice zero, se eu colocasse a imagem 0, eu não precisaria dessa condição
//a primeira imagem automaticamente seria a 0
void MudarImagem()
{
  
    //Condição pra imagem começar pelo indíce 0
    if(indiceImagemAtual == 0)
    {
        ImagemJogo.sprite = sprites[indiceImagemAtual]; //imagem vai ser mudada
        indiceImagemAtual++;// Aqui ela vai valer 1, na próxima execução do metódo
        //ele vai pra próxima condição
    }
    
    else
    {
        ImagemJogo.sprite = sprites[indiceImagemAtual];
        indiceImagemAtual++;

        //Quando o indice atual for maior que a quantidade de imagens ela vai voltar a zero
        //e vai continuar o loop infinitamente
        if(indiceImagemAtual >= sprites.Length)
        {
            indiceImagemAtual = 0;
        }
    }
   
}
//Método pra mudar o tamnho do slider, pode ser usado valores personalizados
//Se não quiser que ele mude é só não chamar no método AtualizarVida
public void MudarTamanhoDoSlider(int altura, int largura)
{
    RectTransform rectTransform = barraDeVida.GetComponent<RectTransform>();
    rectTransform.sizeDelta = new Vector2(altura, largura);
}


public int AtualizarVidaMaxima(int vidaMaxima)
{
    //toda vez que esse método for chamado ele vai atualizar a vida maxima
    //e a vida atual do player
    barraDeVida.maxValue = vidaMaxima;
    barraDeVida.value = vidaMaxima;//Se quiser que a vida atual não seja atualizada é só remover essa linha
    return this.vidaMaxima = vidaMaxima;
}

public void AumentarItensColetados()
{
    panelItens.SetActive(true);//Mostrar painel na tela toda vez que o item for coletado
    itensColetados++;
    Time.timeScale = 0;//o jogo vai ser parado quando o painel estiver ativo,
    //pode remover essa linha se quiser que o jogo conntinue
    
}

//Método pra ser chamado no evento de OnClick do botão
public void FecharPainel()
{
    panelItens.SetActive(false);//Mostrar painel na tela toda vez que o item for coletado
    Time.timeScale = 1;//Despausar o jogo
}


public void AtualizarVida()
{
    //Aqui ele vai atualizar tanto o valor do slider, quanto da vida máxima
    //como essa condição não está sendo chamada no update, deve ser colocado o valor desejado -1;
    if (itensColetados >= 4)//apesar de ser 4, ela vai atualizar quando chegar a 5
    {
        AtualizarVidaMaxima(110);
        MudarTamanhoDoSlider(1000, 160);
        vidaMaxima = (int)barraDeVida.maxValue;
        vidaAtual = (int)barraDeVida.value;
    }
}


private void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.collider.gameObject.CompareTag("Coletavel")) //Tag "Coletavel" Pode ser mudada
    {
        AtualizarVida();
        AumentarItensColetados();
        MudarImagem();

    }
}

}

Você tem que criar uma imagem dentro do painel, depois disso você tem que importar as 4 imagens pra unity

Mudar o tipo das imagens pra sprite 2d, e em sprite Mode marcar como single.

Depois disso vai arrastar as 4 imagens pra dentro da variável sprites no script

Colocar a imagen que você criou no canvas pra dentro de imagem do jogo
Captura de Tela (191)

A imagem que está no canvas não precisa começar com nenhum sprite, deixa ela vazia mesmo

A cada colisão ela muda, quando ela completa todos sprites tudo volta a se repetir, mas da pra mudar isso se for necessário

Eu criei um metodo de dar dano dentro do script que você fez( quando apertar a tecla L), mas o slider nao se mexe.

public void LevarDano(int danoParaReceber)
{
if (jogadorVivo)
{
vidaAtual -= danoParaReceber;

    if (vidaAtual <= 0)
    {
        jogadorVivo = false;
        Debug.Log("Game Over");
    }
}

}

Aqui o script com a modificação que eu fiz em cima

using UnityEngine;
using UnityEngine.UI;

public class VidaDoPlayer : MonoBehaviour
{
//Colocar esse script no player

[SerializeField] private Image ImagemJogo; // Aqui vai a imagem criada no canvas
[SerializeField] private Sprite [] sprites; // Mover as 4 imagens aqui
[SerializeField] private GameObject panelItens;//arrastar o painel aqui

private int indiceImagemAtual = 0;//ImagemAtual
public bool jogadorVivo;



public Slider barraDeVida; //Arrastar o slider pra cá
public int vidaMaxima;
public int vidaAtual;
public int itensColetados;


private void Start()
{
    //Como eu to lidando apenas com valores inteiros eu converti pra int
    //Mas o melhor deveria ser usar float, porque max value e value são float
    vidaMaxima = (int)barraDeVida.maxValue;
    vidaAtual = (int)barraDeVida.value;
}

//Como eu não adicionei nenhum sprite a imagem no canvas,eu fiz uma condição pra ela sempre 
//começar pelo indice zero, se eu colocasse a imagem 0, eu não precisaria dessa condição
//a primeira imagem automaticamente seria a 0
void MudarImagem()
{

    //Condição pra imagem começar pelo indíce 0
    if (indiceImagemAtual == 0)
    {
        ImagemJogo.sprite = sprites[indiceImagemAtual]; //imagem vai ser mudada
        indiceImagemAtual++;// Aqui ela vai valer 1, na próxima execução do metódo
                            //ele vai pra próxima condição
    }

    else
    {
        ImagemJogo.sprite = sprites[indiceImagemAtual];
        indiceImagemAtual++;

        //Quando o indice atual for maior que a quantidade de imagens ela vai voltar a zero
        //e vai continuar o loop infinitamente
        if (indiceImagemAtual >= sprites.Length)
        {
            indiceImagemAtual = 0;
        }
    }

}


public void LevarDano(int danoParaReceber)
{
    if (jogadorVivo)
    {
        vidaAtual -= danoParaReceber;

        if (vidaAtual <= 0)
        {
            jogadorVivo = false;
            Debug.Log("Game Over");
        }
    }
}



//Método pra mudar o tamnho do slider, pode ser usado valores personalizados
//Se não quiser que ele mude é só não chamar no método AtualizarVida
public void MudarTamanhoDoSlider(int altura, int largura)
{
    RectTransform rectTransform = barraDeVida.GetComponent<RectTransform>();
    rectTransform.sizeDelta = new Vector2(altura, largura);
}


public int AtualizarVidaMaxima(int vidaMaxima)
{
    //toda vez que esse método for chamado ele vai atualizar a vida maxima
    //e a vida atual do player
    barraDeVida.maxValue = vidaMaxima;
    barraDeVida.value = vidaMaxima;//Se quiser que a vida atual não seja atualizada é só remover essa linha
    return this.vidaMaxima = vidaMaxima;
}

public void AumentarItensColetados()
{
    panelItens.SetActive(true);//Mostrar painel na tela toda vez que o item for coletado
    itensColetados++;
    Time.timeScale = 0;//o jogo vai ser parado quando o painel estiver ativo,
                       //pode remover essa linha se quiser que o jogo conntinue

}

//Método pra ser chamado no evento de OnClick do botão
public void FecharPainel()
{
    panelItens.SetActive(false);//Mostrar painel na tela toda vez que o item for coletado
    Time.timeScale = 1;//Despausar o jogo
}


public void AtualizarVida()
{
    //Aqui ele vai atualizar tanto o valor do slider, quanto da vida máxima
    //como essa condição não está sendo chamada no update, deve ser colocado o valor desejado -1;
    if (itensColetados >= 4)//apesar de ser 4, ela vai atualizar quando chegar a 5
    {
        AtualizarVidaMaxima(110);
        MudarTamanhoDoSlider(550, 150);
        vidaMaxima = (int)barraDeVida.maxValue;
        vidaAtual = (int)barraDeVida.value;
    }
}


private void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.collider.gameObject.CompareTag("PedacoDeVida")) //Tag "Coletavel" Pode ser mudada
    {
        Destroy(hit.gameObject);
        AtualizarVida();
        AumentarItensColetados();
        MudarImagem();


    }
}

}

1 curtida

Como eu posso alterar o texto de coletar?(Pegue mais 2, peguei mais 3)
Porque até agora mostra a mesma coisa nos 4 casos.


1 curtida

using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class VidaDoPlayer : MonoBehaviour
{
//Colocar esse script no player

[SerializeField] private Image ImagemJogo; // Aqui vai a imagem criada no canvas
[SerializeField] private Sprite[] sprites; // Mover as 4 imagens aqui
[SerializeField] private GameObject panelItens;//arrastar o painel aqui
[SerializeField] private TMP_Text textPainel;//Criar um text no canvas

private int indiceImagemAtual = 0;//ImagemAtual
private string[] textos = { "Texto1", "Texto2", "Texto3", "Texto4" };//alTerar os textos que aparecem no painel

public Slider barraDeVida; //Arrastar o slider pra cá
public int vidaMaxima;
public int vidaAtual;
public int itensColetados;
public bool jogadorVivo;


private void Start()
{
    jogadorVivo = true;
    //Como eu to lidando apenas com valores inteiros eu converti pra int
    //Mas o melhor deveria ser usar float, porque max value e value são float
    vidaMaxima = (int)barraDeVida.maxValue;
    vidaAtual = (int)barraDeVida.value;
}

private void Update()
{
    
    if (Input.GetKeyDown(KeyCode.L))
    {
        LevarDano(10);
    }
}

//Como eu não adicionei nenhum sprite a imagem no canvas,eu fiz uma condição pra ela sempre 
//começar pelo indice zero, se eu colocasse a imagem 0, eu não precisaria dessa condição
//a primeira imagem automaticamente seria a 0
void MudarImagem()
{

    //Condição pra imagem começar pelo indíce 0
    if (indiceImagemAtual == 0)
    {
        textPainel.text = textos[indiceImagemAtual];
        ImagemJogo.sprite = sprites[indiceImagemAtual]; //imagem vai ser mudada
        indiceImagemAtual++;// Aqui ela vai valer 1, na próxima execução do metódo
                            //ele vai pra próxima condição
    }

    else
    {
        textPainel.text = textos[indiceImagemAtual];
        ImagemJogo.sprite = sprites[indiceImagemAtual];
        indiceImagemAtual++;

        //Quando o indice atual for maior que a quantidade de imagens ela vai voltar a zero
        //e vai continuar o loop infinitamente
        if (indiceImagemAtual >= sprites.Length)
        {
            indiceImagemAtual = 0;
        }
    }

}


public void LevarDano(int danoParaReceber)
{
    if (jogadorVivo)
    {
       barraDeVida.value = ( vidaAtual -= danoParaReceber);//Ajustei pro slider funcionar agora
        

        if (vidaAtual <= 0)
        {
            jogadorVivo = false;
            Debug.Log("Game Over");
        }
    }
}



//Método pra mudar o tamnho do slider, pode ser usado valores personalizados
//Se não quiser que ele mude é só não chamar no método AtualizarVida
public void MudarTamanhoDoSlider(int altura, int largura)
{
    RectTransform rectTransform = barraDeVida.GetComponent<RectTransform>();
    rectTransform.sizeDelta = new Vector2(altura, largura);
}


public int AtualizarVidaMaxima(int vidaMaxima)
{
    //toda vez que esse método for chamado ele vai atualizar a vida maxima
    //e a vida atual do player
    barraDeVida.maxValue = vidaMaxima;
    barraDeVida.value = vidaMaxima;//Se quiser que a vida atual não seja atualizada é só remover essa linha
    return this.vidaMaxima = vidaMaxima;
}

public void AumentarItensColetados()
{
    panelItens.SetActive(true);//Mostrar painel na tela toda vez que o item for coletado
    itensColetados++;
    Time.timeScale = 0;//o jogo vai ser parado quando o painel estiver ativo,
                       //pode remover essa linha se quiser que o jogo conntinue

}

//Método pra ser chamado no evento de OnClick do botão
public void FecharPainel()
{
    panelItens.SetActive(false);//Mostrar painel na tela toda vez que o item for coletado
    Time.timeScale = 1;//Despausar o jogo
}


public void AtualizarVida()
{
    //Aqui ele vai atualizar tanto o valor do slider, quanto da vida máxima
    //como essa condição não está sendo chamada no update, deve ser colocado o valor desejado -1;
    if (itensColetados >= 4)//apesar de ser 4, ela vai atualizar quando chegar a 5
    {
        AtualizarVidaMaxima(110);
        MudarTamanhoDoSlider(550, 150);
        vidaMaxima = (int)barraDeVida.maxValue;
        vidaAtual = (int)barraDeVida.value;
    }
}


private void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.collider.gameObject.CompareTag("PedacoDeVida")) //Tag "Coletavel" Pode ser mudada
    {
        Destroy(hit.gameObject);
        AtualizarVida();
        AumentarItensColetados();
        MudarImagem();


    }
}

}

Agora é so criar o texto e arrastar pro script

No script eu criei um vetor de string pra colocar os textos, é só escrever lá. Mas detalhe que essa é uma solução rápida, mas não a melhor, porque caso tu fosse traduzir o jogo seria muito complicado fazer tradução por script, a unity tem uma ferramento pra isso, eu pensei em usar scriptable objects, mas ai é mais complicado, eu digo isso porque caso tu pretenda algum dia criar um jogo e traduzir já tenha isso em mente.
E também ajustei pro slider diminuir conforme ele perca vida, o problema é que só a várial “vidaAtual” estava diminuindo. Outro problema é que a váriavel “jogadoVivo” estava começando como falsa, não sei se tu tava marcando como true no inspector, mas ai eu coloquei ela no start como true.

Muito obrigado, vou testar aqui.

1 curtida