Inscreva-se em OnEnable
Parte da seção Arquitetura de Jogos no Unity do Journey de Unity da Coddy. Lição 13 de 64.
Um ouvinte que é destruído não deixa o evento por conta própria. O evento ainda mantém seu método, e o próximo Invoke o chama no componente destruído. O primeiro uso de transform nesse método lança uma MissingReferenceException e, como uma exceção encerra o Invoke, os ouvintes que vêm depois também são ignorados. Portanto, cada += precisa de um -=, e o par de métodos do Unity para isso é OnEnable e OnDisable:
public class Guard : MonoBehaviour
{
public Alarm alarm;
void OnEnable()
{
alarm.OnTriggered += RunTo;
}
void OnDisable()
{
alarm.OnTriggered -= RunTo;
}
void RunTo(Vector3 spot)
{
transform.LookAt(spot);
}
}O Unity chama OnDisable quando o objeto é desativado com SetActive(false), quando o script é desabilitado e quando o objeto é destruído, antes de OnDestroy. OnEnable é executado toda vez que ele é ativado novamente. Com esse par, um guarda ouve exatamente enquanto está ativo: um guarda destruído deixa de fazer parte do evento, um guarda desativado durante uma cena ignora o alarme e, quando é ativado novamente, volta a ouvir.
Dois outros pareamentos dão errado. Com += em Start e -= em OnDisable, um guarda desativado e ativado novamente nunca mais ouve, porque Start é executado apenas uma vez. Com += em OnEnable e sem -=, cada retorno adiciona RunTo novamente, e um alarme o chama duas vezes. Remover um método que não está inscrito não faz nada, então nunca é necessário verificar antes de usar -= em OnDisable.
Desafio
FácilFaça com que cada aldeão ouça o sino somente enquanto estiver ativo.
- Em
Villager.cs, movabell.OnRing += Hop;deStart()para um novovoid OnEnable()e excluaStart(). - Adicione
void OnDisable()combell.OnRing -= Hop;. O botão “Verificar” desativa e ativa Cleo para testar isso.
Pressione “Jogar” e toque o sino quatro vezes: Ana vai para casa depois do toque 2, e nenhum erro aparece. Em seguida, pressione “Verificar”.
Experimente você mesmo
using UnityEngine;
public class Villager : MonoBehaviour
{
public Bell bell;
public int ringsToLeave = 3;
public int hops;
void Start()
{
bell.OnRing += Hop;
}
void Update()
{
// volte ao chão depois de um salto
Vector3 p = transform.position;
transform.position = new Vector3(p.x, Mathf.MoveTowards(p.y, 0.5f, 4f * Time.deltaTime), p.z);
}
void Hop(int ring)
{
hops++;
transform.position += Vector3.up * 0.8f;
if (hops == ringsToLeave)
{
Debug.Log(name + " goes home");
Destroy(gameObject);
}
}
}
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