Indice dei contenuti
Proseguiamo il nostro viaggio nella realizzazione di un roguelike 2D con Unity. Nella prima parte abbiamo creato il progetto, impostato la grafica e implementato il movimento del personaggio. Ora è giunto il momento di dare vita al dungeon: aggiungeremo i nemici, programmeremo un'IA di base per inseguire il giocatore, e implementeremo un semplice sistema di combattimento.
Ricordiamo che tutto il codice di riferimento è disponibile nel repository GitHub ufficiale 2DRogueTest, che vi consigliamo di consultare per assicurarvi di visionare il codice sorgente aggiornato all'ultima versione!
1. Aggiunta dei nemici
Nel progetto troviamo già il prefab del nemico base: /Prefabs/Enemy.prefab
. Questo GameObject include:
- uno
SpriteRenderer
con lo spriteenemy.png
- un
Rigidbody2D
(Body Type: Dynamic) - un
BoxCollider2D
- lo script
EnemyController.cs
presente in/Scripts/EnemyController.cs
L'enemy prefab può essere istanziato manualmente nella scena oppure tramite script.
2. Movimento verso il player (IA base)
Lo script EnemyController.cs
contiene una logica semplice ma efficace per inseguire il giocatore:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class EnemyController : MonoBehaviour { public float speed = 3.0f; private Rigidbody2D rb; private Transform player; void Start() { rb = GetComponent<Rigidbody2D>(); player = GameObject.FindGameObjectWithTag("Player").transform; } void FixedUpdate() { if (player != null) { Vector2 direction = (player.position - transform.position).normalized; rb.MovePosition(rb.position + direction * speed * Time.fixedDeltaTime); } } } |
Questa semplice IA fa muovere ogni nemico verso il giocatore, con velocità costante. Assicurati che il player abbia il tag Player
impostato.
3. Sistema di combattimento
Per aggiungere un sistema di danno e morte, ogni entità (player e nemici) deve avere un sistema di punti vita. Nel progetto troviamo uno script riutilizzabile chiamato EntityStats.cs
in /Scripts/EntityStats.cs
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class EntityStats : MonoBehaviour { public int maxHP = 3; public int currentHP; void Awake() { currentHP = maxHP; } public void TakeDamage(int amount) { currentHP -= amount; if (currentHP <= 0) { Die(); } } protected virtual void Die() { Destroy(gameObject); } } |
Lo script PlayerController.cs
è stato aggiornato per attaccare i nemici quando preme il tasto Space. Nel metodo Update()
troviamo:
1 2 3 4 |
if (Input.GetKeyDown(KeyCode.Space)) { TryAttack(); } |
E la funzione TryAttack()
è definita così:
1 2 3 4 5 6 7 8 9 10 11 |
void TryAttack() { Collider2D[] hits = Physics2D.OverlapCircleAll(transform.position, 0.5f); foreach (var hit in hits) { if (hit.CompareTag("Enemy")) { hit.GetComponent<EntityStats>()?.TakeDamage(1); } } } |
Questo attacco ad area semplice colpisce ogni nemico nel raggio di 0.5 unità.
Nota:
- I nemici devono avere il tag
Enemy
. - Lo script
EntityStats
deve essere aggiunto sia al player che ai nemici.
4. Sistema di danno al giocatore
Anche i nemici possono infliggere danno. Nello script EnemyController.cs
, puoi aggiungere questo metodo:
1 2 3 4 5 6 7 |
void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.CompareTag("Player")) { collision.gameObject.GetComponent<EntityStats>()?.TakeDamage(1); } } |
In questo modo, ogni volta che un nemico tocca il player, infligge 1 danno.
Puoi migliorare questo sistema con un cooldown tra gli attacchi, animazioni e feedback visivi.
5. Feedback visivo e polish
Nel progetto sono inclusi:
- animazioni per nemici e player in
/Animations
- effetti sonori placeholder
- logiche base per far lampeggiare i nemici quando ricevono danno
Tutto è opzionale ma migliora l'esperienza.
Conclusione
In questa seconda parte abbiamo dato vita al dungeon: i nemici inseguono il giocatore, lo attaccano, e possono essere sconfitti. Tutto è gestito tramite script semplici e modulari, tutti presenti nel repository 2DRogueTest.
Nella terza e ultima parte vedremo come generare automaticamente le stanze, collegarle tra loro, e rendere ogni partita unica.