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?
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:
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
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.
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
}
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
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
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();
}
}
}
Como eu posso alterar o texto de coletar?(Pegue mais 2, peguei mais 3)
Porque até agora mostra a mesma coisa nos 4 casos.
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.