Componentes abstractos
Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 3 de 64.
Algunas clases base describen un tipo de cosa que nunca existe por sí sola. Todas las armas disparan, pero un arma que no es ni una pistola ni una escopeta no tiene forma de disparar. Marca una clase así como abstract y declara cada paso que sus subclases deben implementar como un método abstracto, sin cuerpo:
public abstract class Weapon : MonoBehaviour
{
public int shots;
public void Pull()
{
shots++;
Fire();
}
protected abstract void Fire();
}public class Shotgun : Weapon
{
public GameObject pelletPrefab;
protected override void Fire()
{
for (int i = -1; i <= 1; i++)
{
Instantiate(pelletPrefab, transform.position + transform.right * i * 0.3f, transform.rotation);
}
}
}Una subclase que no implemente Fire no compila: CS0534, 'Pistol' does not implement inherited abstract member 'Weapon.Fire()'. Unity tampoco permite añadir un script abstracto a un objeto. Arrastra Weapon sobre uno y aparecerá Can't add script behaviour 'Weapon'. The script class can't be abstract!, ya que Unity no podría crear un Weapon sin Fire.
Los demás scripts siguen funcionando con el tipo base. GetComponent<Weapon>() devuelve la subclase que haya en el objeto, y Pull() ejecuta el Fire de esa subclase:
// Player.cs
private Weapon weapon;
void Start()
{
weapon = GetComponent<Weapon>();
}
void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
weapon.Pull();
}
}Cambia el componente Shotgun por uno Pistol y el script Player seguirá igual.
Desafío
FácilHaz que Monster sea abstracta y que la torre lance rayos a todos los tipos de monstruos.
- En
Monster, escribepublic abstract class Monsteryprotected abstract void React();, sin cuerpo. - Ahora el compilador señala
Imp: añadeprotected override void React()que sumeVector3.forward * 2fa su posición. - En
Tower, dentro del bucle, llama aZap()entarget.GetComponent<Monster>().
Pulsa «Jugar» y la barra espaciadora: los slimes se encogen y el imp salta hacia atrás. Después, pulsa «Comprobar».
Pruébalo tú mismo
using UnityEngine;
// Lo que comparten todos los monstruos.
public class Monster : MonoBehaviour
{
public int hp = 3;
public void Zap()
{
hp--;
if (hp <= 0)
{
Destroy(gameObject);
}
else
{
React();
}
}
// Cómo reacciona este tipo de monstruo a una descarga que sobrevive.
protected virtual void React()
{
}
}
Todas las lecciones de Arquitectura de juegos en Unity
1Componentes, no jerarquías
Componentes pequeñosUn script base para enemigosComponentes abstractosComponentes que trabajan juntosRepaso: torreta modularRepaso: cañón doble4Datos serializados
Clases serializablesListas en el InspectorEnumeraciones en el InspectorRepaso: tabla de botínRepaso: sortear el botín2Interfaces en Unity
IDamageableInterfaces y TryGetComponentGetComponentsRepaso: Tecla de interacciónRepaso: El más cercano al alcance5ScriptableObjects
Activos de datosEstadísticas de armasConfiguración compartidaGuardar el vientoOleadas como datosRepaso: base de datos de objetosRepaso: comprar en la tienda3Eventos
Eventos de C# en UnitySuscribirse en OnEnableCampos UnityEventLos eventos controlan la interfazRepaso: ventana emergente de logrosRepaso: temporizador de la ventana emergentePractica por tu cuenta: Playground de Unity