Eventos de C# no Unity
Parte da seção Arquitetura de Jogos no Unity do Journey de Unity da Coddy. Lição 12 de 64.
Quando a pontuação muda, várias coisas se importam: o texto da pontuação, um som, uma conquista. Se o ScoreKeeper chamar cada uma delas, precisará de um campo para cada uma, e cada novo recurso significará editá-lo. Um evento inverte essa lógica: o ScoreKeeper anuncia a mudança, e quem se importa se inscreve.
Duas palavras de C# fazem isso funcionar. Action<int> é o tipo de um método que recebe um int e não retorna nada. Um event desse tipo é uma lista desses métodos: outro código adiciona seu método com +=, e o proprietário chama todos eles com Invoke. Em C# puro:
using System;
class Alarm
{
public event Action<int> Rang;
public void Ring(int hour)
{
Rang?.Invoke(hour);
}
}
class Sleeper
{
public void WakeUp(int hour)
{
Console.WriteLine("Up at " + hour);
}
}
// em outro lugar
Alarm alarm = new Alarm();
Sleeper sleeper = new Sleeper();
alarm.Rang += sleeper.WakeUp;
alarm.Ring(7); // De pé às 7No Unity, o publicador e seus ouvintes são componentes, geralmente em GameObjects diferentes:
using System;
using UnityEngine;
public class ScoreKeeper : MonoBehaviour
{
public event Action<int> OnScoreChanged;
private int score;
public void AddPoints(int points)
{
score += points;
OnScoreChanged?.Invoke(score);
}
}// ScoreLabel.cs, no texto do HUD
public ScoreKeeper keeper;
public TMP_Text label;
void Start()
{
keeper.OnScoreChanged += ShowScore;
}
void ShowScore(int score)
{
label.text = "Score: " + score;
}Action<int> significa que cada ouvinte é um método que recebe um int, neste caso, a nova pontuação. Invoke chama todos os métodos inscritos, na ordem em que se inscreveram. Sem ouvintes, o evento é null, então uma chamada simples como OnScoreChanged(score) lançaria uma NullReferenceException, enquanto ?. ignora a chamada. A palavra-chave event limita outros scripts a += e -=: em ScoreLabel, keeper.OnScoreChanged(5) ou keeper.OnScoreChanged = null não compila.
O ScoreKeeper não tem um campo para o rótulo e não sabe que ele existe. Um contador de combos ou um reprodutor de som se inscreve da mesma maneira, e o ScoreKeeper continua igual; uma cena de teste sem HUD é executada sem erros. Um ouvinte encontra o publicador por meio de uma referência no Inspector, como aqui, ou de qualquer outra forma que você conheça, como GetComponent ou um singleton. Remover um ouvinte com -= é importante quando os objetos são destruídos, assunto da próxima lição.
Desafio
FácilFaça o lutador anunciar seu combo.
- Em
Fighter.cs, adicioneusing System;epublic event Action<int> OnComboChanged;. - Substitua as linhas que usam
comboTexteflameporOnComboChanged?.Invoke(combo);e exclua os dois campos. - No
Start()deComboTexteComboFlame, escrevafighter.OnComboChanged += Show;e+= Grow;.
Pressione “Jogar” e aperte Espaço algumas vezes: o combo aumenta e depois zera. Em seguida, clique em “Verificar”.
Experimente você mesmo
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class Fighter : MonoBehaviour
{
public float comboWindow = 1f;
public TMP_Text comboText;
public Transform flame;
private int combo;
private float sinceHit;
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
combo++;
sinceHit = 0f;
comboText.text = "Combo x" + combo;
flame.localScale = Vector3.one * (0.5f + 0.25f * combo);
}
else if (combo > 0)
{
sinceHit += Time.deltaTime;
if (sinceHit > comboWindow)
{
combo = 0;
comboText.text = "";
flame.localScale = Vector3.one * 0.5f;
}
}
}
}
Todas as lições de Arquitetura de Jogos no Unity
1Componentes, não hierarquias
Componentes pequenosUm script base de inimigoComponentes abstratosComponentes trabalhando juntosRevisão: torre modularRevisão: canhão duplo4Dados Serializados
Classes SerializáveisListas no InspectorEnums no InspectorRevisão: Tabela de LootRevisão: Sorteie o Loot2Interfaces no Unity
IDamageableInterfaces e TryGetComponentGetComponentsRevisão: tecla de interaçãoRevisão: mais próximo ao alcance5ScriptableObjects
Ativos de DadosAtributos da ArmaConfigurações CompartilhadasSalve o VentoOndas como DadosRevisão: Banco de ItensRevisão: Comprar na LojaPratique por conta própria: Playground de Unity