Transizioni
Fa parte della sezione Architettura dei giochi in Unity del percorso Unity di Coddy. Lezione 38 di 64.
Chi decide quando cambia lo stato? Affidare la decisione al proprietario riporterebbe tutte le regole in un unico Update, come faceva lo switch. Di solito, ogni stato conosce il proprio modo di uscirne: nel suo Tick controlla la condizione e chiede alla macchina di passare allo stato successivo. Questa bomba aspetta che il giocatore si avvicini, poi brucia la miccia e torna in attesa se il giocatore scappa:
public class Bomb : MonoBehaviour
{
public Transform player;
public StateMachine machine = new StateMachine();
public IState idle;
public IState fuse;
void Start()
{
idle = new IdleState(this);
fuse = new FuseState(this);
machine.ChangeState(idle);
}
void Update() { machine.Tick(); }
public bool PlayerNear()
{
return Vector3.Distance(transform.position, player.position) < 3f;
}
}
public class IdleState : IState
{
private Bomb bomb;
public IdleState(Bomb bomb) { this.bomb = bomb; }
public void Enter() { }
public void Exit() { }
public void Tick()
{
if (bomb.PlayerNear()) bomb.machine.ChangeState(bomb.fuse);
}
}
public class FuseState : IState
{
private Bomb bomb;
private float timer;
public FuseState(Bomb bomb) { this.bomb = bomb; }
public void Enter() { timer = 2f; }
public void Exit() { }
public void Tick()
{
if (!bomb.PlayerNear())
{
bomb.machine.ChangeState(bomb.idle);
return;
}
timer -= Time.deltaTime;
if (timer <= 0f)
{
Debug.Log("Boom!");
Object.Destroy(bomb.gameObject);
}
}
}Ogni stato riceve la bomba nel proprio costruttore e vi accede per raggiungere la macchina, verificare la presenza del giocatore e ottenere gli altri stati. La bomba crea ogni stato una sola volta, in Start, quindi uno stato non ne crea un altro con new: due stati che si creassero a vicenda nei rispettivi costruttori continuerebbero a richiamarsi fino all'esaurimento dello stack. L'Update della bomba si limita a eseguire il Tick della macchina, mentre le regole si trovano negli stati a cui appartengono: la miccia di 2 secondi è una responsabilità esclusiva di FuseState.
ChangeState esegue subito Exit di FuseState ed Enter di IdleState, ma il resto del Tick di FuseState verrebbe comunque eseguito dopo la chiamata. return lo interrompe; altrimenti la miccia brucerebbe ancora per un fotogramma, anche se lo stato è già terminato. Destroy è scritto Object.Destroy: un MonoBehaviour eredita questo metodo dalla classe Object di Unity, mentre una classe semplice deve specificare il nome della classe.
Sfida
MedioScrivi le transizioni della dionea in ogni Tick di FlytrapStates.cs.
- Open: quando
trap.PlayerInReach(), chiamatrap.machine.ChangeState(trap.snap);. - Snap: aggiungi
Time.deltaTimeatimer; a0.5, passa atrap.chewse il giocatore è ancora a portata, altrimenti atrap.open. - Chew: fai scendere
timerda 3; a 0, passa atrap.open.
Premi «Gioca», entra nella trappola e poi schivala. Poi premi «Verifica».
Provalo tu
using UnityEngine;
public class OpenState : IState
{
private Flytrap trap;
public OpenState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
trap.Paint(new Color(0.3f, 0.8f, 0.2f));
}
public void Tick()
{
// Scatta quando il giocatore è a portata
}
public void Exit()
{
}
}
public class SnapState : IState
{
private Flytrap trap;
private float timer;
public SnapState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
timer = 0f;
trap.Paint(new Color(1f, 0.55f, 0.1f));
}
public void Tick()
{
// Dopo 0.5 secondi: mastica se il giocatore è ancora a portata, altrimenti riapriti
}
public void Exit()
{
}
}
public class ChewState : IState
{
private Flytrap trap;
private float timer;
public ChewState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
timer = 3f;
trap.Paint(new Color(0.5f, 0.05f, 0.1f));
Debug.Log("Chomp!");
}
public void Tick()
{
// Dopo 3 secondi: riapriti
}
public void Exit()
{
}
}
Tutte le lezioni di Architettura dei giochi in Unity
1Componenti, non gerarchie
Componenti piccoliUno script base per i nemiciComponenti astrattiComponenti che collaboranoRipasso: torretta modulareRipasso: cannone doppio4Dati serializzati
Classi serializzabiliElenchi nell'InspectorEnum nell'InspectorRiepilogo: tabella del bottinoRiepilogo: tira il bottino2Interfacce in Unity
IDamageableInterfacce e TryGetComponentGetComponentsRiepilogo: tasto InteragisciRiepilogo: il più vicino a portata5ScriptableObjects
Asset di datiStatistiche delle armiImpostazioni condiviseSalva il ventoOnde come datiRiepilogo: database degli oggettiRiepilogo: comprare dal negozioEsercitati da solo: Playground Unity