Interfaces e TryGetComponent
Parte da seção Arquitetura de Jogos no Unity do Journey de Unity da Coddy. Lição 8 de 64.
TryGetComponent procura um componente e informa se encontrou um, tudo em uma única chamada. Também funciona com interfaces, o que faz dele a maneira habitual de verificar se aquilo em que você bateu pode receber dano. Esta mina causa dano a tudo ao redor que seja IDamageable:
public class Mine : MonoBehaviour
{
public float radius = 3f;
public int damage = 5;
void OnTriggerEnter(Collider other)
{
foreach (Collider c in Physics.OverlapSphere(transform.position, radius))
{
if (c.TryGetComponent(out IDamageable target))
{
target.TakeDamage(damage);
}
}
Destroy(gameObject);
}
}out IDamageable target declara a variável dentro da chamada. TryGetComponent retorna true e preenche target quando o objeto tem um componente que implementa IDamageable; caso contrário, retorna false e target é null. Ele verifica apenas aquele objeto, nunca o pai nem os filhos.
GetComponent trata um componente ausente de classe e um componente ausente de interface de maneiras diferentes. No Editor, GetComponent<Rigidbody>() em um objeto sem Rigidbody retorna o null falso do Unity: == null é true, mas ?. não o detecta e a chamada lança MissingComponentException. Uma interface não tem null falso: GetComponent<IDamageable>() retorna um null real do C#, então == null e ?. funcionam com ele. TryGetComponent evita essa questão nos dois casos e não aloca nada no Editor quando o componente está ausente.
Desafio
FácilEscreva Fire() em Laser: um raio, quatro resultados.
- Dispare
Physics.Raycastda torre na direção detransform.forward, com o comprimento derange. Se não acertar nada, registreMissed. - Se
hit.collider.TryGetComponent(out IDamageable target), chameTakeDamage(damage)e registre"Hit " + hit.collider.name. - Caso contrário, se tiver um
Rigidbody, apliqueAddForce(transform.forward * push, ForceMode.Impulse)e registre"Pushed "junto com o nome; caso contrário,"Blocked by "junto com o nome.
Pressione “Jogar”, vire-se e atire em todas as direções. Depois, “Verificar”.
Experimente você mesmo
using UnityEngine;
using UnityEngine.InputSystem;
public class Laser : MonoBehaviour
{
public float range = 10f;
public int damage = 1;
public float push = 5f;
public float turnSpeed = 90f;
private InputAction moveAction;
void Start()
{
moveAction = InputSystem.actions.FindAction("Move");
}
void Update()
{
float turn = moveAction.ReadValue<Vector2>().x;
transform.Rotate(0f, turn * turnSpeed * Time.deltaTime, 0f);
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
Fire();
}
}
void Fire()
{
// Emita um raio para a frente, com comprimento de range unidades, e lide com o que ele atingir
}
}
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