Interfaces e TryGetComponent
Parte da seção Arquitetura de jogos no Unity do Journey de Unity da Coddy. Lição 7 de 50.
TryGetComponent procura um componente e informa se encontrou um, em uma única chamada. Também funciona com interfaces, o que o torna a forma usual de perguntar ao objeto atingido se ele 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 ou os filhos dele.
GetComponent relata a ausência de uma classe e a ausência de uma interface de formas diferentes. No Editor, GetComponent<Rigidbody>() em um objeto sem Rigidbody retorna o null falso do Unity: == null é true, mas ?. não o reconhece e a chamada lança MissingComponentException. Uma interface não tem null falso: GetComponent<IDamageable>() retorna um null real de C#, então == null e ?. funcionam com ele. TryGetComponent evita essa questão em ambos os casos e não aloca nada no Editor quando o componente está ausente.
Desafio
FácilA torre laser gira com as setas para a esquerda e para a direita, e a tecla Espaço chama Fire() em Laser.cs. Escreva Fire. Lance um raio da torre na direção para a qual ela está voltada, com comprimento de range unidades (o Inspector define 10), depois:
- Se atingir algo que tenha um IDamageable, chame
TakeDamage(damage)nele e registreHite o nome do objeto, comoHit Robot. - Se o objeto não tiver IDamageable, mas tiver um Rigidbody, empurre-o com
AddForce(transform.forward * push, ForceMode.Impulse)e registrePushede o nome dele. - Qualquer outra coisa registra
Blocked bye o nome dela, comoBlocked by Pillar. Um raio que não atingir nada registraMissed.
Use TryGetComponent para ambas as buscas. IDamageable.cs, Robot.cs e Balloon.cs estão prontos. Pressione Jogar 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()
{
// Lance um raio para a frente, com comprimento de range unidades, e lide com o que ele atingir
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Arquitetura de jogos no Unity
1Componentes, não hierarquias
Componentes pequenosUm script-base para inimigosComponentes abstratosComponentes trabalhando juntosRevisão: Torre modular4Dados Serializados
Classes SerializáveisListas no InspectorEnums no InspectorRevisão: Tabela de Loot7Máquinas de Estados
Estados como ClassesUma Máquina de EstadosTransiçõesInteligências dos InimigosRevisão: Estados da Porta10Projeto: Sobrevivente da Arena
O HeróiTipos de Inimigos5ScriptableObjects
Assets de dadosAtributos das armasConfigurações compartilhadasOndas como dadosRevisão: banco de dados de itens