Godot 4 per Android con C#: Scene, Nodi e Segnali

Godot 4 per Android con C#: Scene, Nodi e Segnali (Bozza)

Stato: bozza non pubblicata. Questo articolo fa parte della serie “Godot 4 per Android con C#” e approfondisce il cuore dell’architettura di Godot: scene, nodi e segnali, con esempi pratici orientati al deployment su dispositivi Android.

1. Introduzione: perché scene, nodi e segnali contano su Android

In Godot 4 tutto ruota attorno a scene e nodi. Che tu stia creando un semplice gioco 2D o una UI complessa per Android, capire come organizzare la gerarchia dei nodi e come farli comunicare tramite segnali è fondamentale per avere codice pulito, riutilizzabile e facile da debuggare su emulatore e dispositivo reale.

In questa terza bozza della serie vedremo come strutturare una scena con Node2D e Control, come collegare script C# ai nodi, come usare correttamente i metodi di ciclo di vita _Ready() e _Process(), e come dichiarare/collegare segnali per gestire l’interazione touch (es. un pulsante che aggiorna una Label).

2. Obiettivi della guida

  • Capire la differenza tra scena e nodo in Godot 4.
  • Conoscere i nodi base più usati per Android: Node2D (logica/gioco 2D) e Control (UI).
  • Imparare a organizzare una scena pensata per touchscreen Android.
  • Collegare uno script C# a un nodo e usare i metodi _Ready() e _Process(double delta).
  • Dichiarare e collegare segnali personalizzati e integrati (come il click di un bottone).
  • Creare un esempio completo: un pulsante touch che aggiorna una Label sullo schermo.
  • Capire come testare la scena su emulatore e su dispositivo Android reale.
  • Introdurre concetti avanzati di riuso delle scene e gestione del ciclo di vita su Android.

3. Ambiente di lavoro: prerequisiti e contesto Android

Questa bozza dà per scontato che tu abbia già:

  • Installato Godot 4.x .NET (versione con supporto C#).
  • Configurato il SDK Android e creato almeno un progetto Android Godot (vedi articoli precedenti della serie).
  • Configurato un emulatore Android (es. tramite Android Studio) oppure un dispositivo fisico con debug USB attivo.

Se sei già abituato alle app Android in Java o Kotlin, puoi vedere una scena di Godot come l’equivalente di un Activity layout riutilizzabile, mentre i nodi sono i singoli componenti (view, widget, logica) che compongono la schermata.

4. Concetti base: scene e nodi in Godot 4

4.1 Cos’è una scena

Una scena in Godot 4 è un albero di nodi salvato come risorsa (file .tscn). Può rappresentare:

  • Un livello di gioco.
  • Un personaggio o un nemico.
  • Un HUD (interfaccia utente).
  • Una schermata di menu per Android.

Ogni scena ha un nodo radice (root) e uno o più nodi figli. Le scene possono essere istanziate e riutilizzate dentro altre scene, permettendoti di organizzare il progetto in modo modulare.

4.2 Cos’è un nodo

Un nodo è un singolo elemento della scena: può avere logica, grafica, input, audio, UI, e così via. Alcuni tipi di nodi fondamentali per Android:

  • Node: la base di tutto, nodo generico senza grafica.
  • Node2D: nodo 2D con posizione, rotazione e scala, ideale per giochi 2D e logica visiva.
  • Control: nodo UI, supporta layout, ancoraggi e dimensioni reattive, perfetto per schermi Android con densità diverse.
  • Button, Label, TextureRect, ecc.: specializzazioni di Control per i vari widget.

In pratica: Node2D per il mondo di gioco, Control per l’interfaccia touch.

5. Node2D e Control: quando usare cosa

5.1 Node2D: logica e oggetti di gioco

Node2D è la base per i nodi 2D. Espone proprietà come Position, Rotation, Scale. Esempi d’uso:

  • Giocatore, nemici, proiettili.
  • Oggetti interattivi sullo schermo.
  • Manager di logica di gioco 2D.

Su Android, un Node2D può gestire ad esempio il movimento di un personaggio in base all’input touch o al giroscopio.

5.2 Control: interfaccia utente reattiva

Control è il nodo base per creare UI reattive. Offre:

  • Anchor (ancoraggi) per posizionare i widget rispetto ai bordi dello schermo.
  • Layout automatici (container) per adattarsi a risoluzioni diverse.
  • Supporto nativo al touch.

Per Android è importante usare i nodi Control correttamente, in modo che pulsanti e label rimangano leggibili su smartphone e tablet con densità differenti.

6. Progettare una scena per Android: struttura consigliata

Per un semplice esempio di app/gioco 2D con UI, una struttura tipica di scena può essere:

  • Main.tscn con root Node2D
    • World (Node2D): logica e oggetti di gioco.
    • CanvasLayer
      • UIRoot (Control)
        • Label
        • Button

In questa bozza useremo una versione semplificata, ma con la stessa idea: separare il mondo di gioco (anche solo logico) dall’interfaccia utente.

7. Creare la scena: passo passo

7.1 Creare la scena principale

1. In Godot 4, crea una nuova scena (Scene > New Scene).
2. Imposta come nodo radice un Node2D e rinominalo in Main.
3. Salva la scena come res://Scenes/Main.tscn (organizza le scene in cartelle, come faresti con i layout in un progetto Android).

7.2 Aggiungere la UI: Label e Button

1. Seleziona il nodo Main.
2. Aggiungi un nodo figlio di tipo Control e rinominalo UIRoot.
3. Dentro UIRoot, aggiungi una Label (rinominala StatusLabel).
4. Sempre dentro UIRoot, aggiungi un Button (rinominalo TapButton).

Assicurati che UIRoot e i suoi figli siano ancorati correttamente (es. Full Rect per UIRoot, Label in alto, Button al centro o in basso) in modo che la UI sia usabile su diversi schermi Android.

8. Collegare uno script C# alla scena

Ora colleghiamo uno script C# al nodo Main per gestire logica, segnali e aggiornamento dell’interfaccia.

  • Seleziona il nodo Main.
  • Clicca su Attach Script.
  • Scegli Language: C#.
  • Salva lo script come res://Scripts/Main.cs.

Godot genererà una classe C# di base. Modifichiamola per gestire la Label e il Button.

using Godot;
using System;

public partial class Main : Node2D
{
    // Riferimenti ai nodi UI
    private Label _statusLabel;
    private Button _tapButton;

    // Contatore di tap per mostrare qualcosa di dinamico
    private int _tapCount = 0;

    public override void _Ready()
    {
        // _Ready viene chiamato quando il nodo e i suoi figli sono entrati nell'albero della scena
        // Qui è sicuro accedere ai nodi tramite GetNode

        _statusLabel = GetNode<Label>("UIRoot/StatusLabel");
        _tapButton = GetNode<Button>("UIRoot/TapButton");

        // Inizializza il testo
        _statusLabel.Text = "Tocca il pulsante per iniziare";

        // Collega il segnale del pulsante al metodo OnTapButtonPressed
        _tapButton.Pressed += OnTapButtonPressed;
    }

    public override void _Process(double delta)
    {
        // _Process viene chiamato ogni frame
        // Qui puoi gestire logica di aggiornamento continua (animazioni, timer, ecc.)
        // Per questo esempio, non facciamo nulla ad ogni frame
    }

    private void OnTapButtonPressed()
    {
        // Questo metodo viene chiamato quando il pulsante viene premuto (touch su Android)
        _tapCount++;

        _statusLabel.Text = $"Pulsante toccato {_tapCount} volta(e)!";
    }
}

Nota: l’uso di _tapButton.Pressed += OnTapButtonPressed; è il modo idiomatico C# per collegare il segnale pressed del pulsante al metodo corrispondente.

9. _Ready e _Process in dettaglio

9.1 Quando usare _Ready()

_Ready() viene chiamato quando il nodo è pronto e tutti i suoi figli sono stati aggiunti all’albero della scena. È il posto giusto per:

  • Recuperare riferimenti ai nodi figli (GetNode).
  • Inizializzare variabili di stato.
  • Collegare segnali tra nodi.

Evita di accedere ai nodi figli nel costruttore C# o in campi statici: su Android (e in generale) potresti trovarti con riferimenti null perché l’albero non è ancora pronto.

9.2 Quando usare _Process(double delta)

_Process(double delta) viene chiamato ogni frame. È utile per:

  • Animazioni personalizzate.
  • Aggiornamento di logica che dipende dal tempo (delta è il tempo in secondi dall’ultimo frame).
  • Controlli continui (es. lettura input ogni frame).

Su Android, ricorda che i dispositivi hanno frequenze di refresh diverse. Usa sempre delta per normalizzare i movimenti nel tempo, evitando logica legata al numero di frame.

public override void _Process(double delta)
{
    // Esempio: muovi un nodo verso destra a velocità costante (pixel al secondo)
    float speed = 100f; // pixel al secondo
    Position += new Vector2(speed * (float)delta, 0);
}

10. Segnali in C#: dichiarazione e collegamento

I segnali in Godot sono eventi che i nodi emettono per comunicare con altri nodi. In C#, puoi usare sia i segnali integrati (come pressed dei pulsanti) sia dichiarare segnali personalizzati.

10.1 Segnali integrati (es. Button.pressed)

Nell’esempio precedente abbiamo collegato il segnale pressed del pulsante in C#:

_tapButton.Pressed += OnTapButtonPressed;

Puoi fare lo stesso anche dall’editor, nella tab Node > Signals, collegando il segnale a un metodo C# esistente. Per progetti Android complessi, preferire il collegamento da codice ti aiuta a mantenere il wiring più esplicito e versionabile.

10.2 Segnali personalizzati in C#

Puoi definire un segnale personalizzato in C# usando l’attributo [Signal]. Esempio: un manager di gioco che avvisa quando il punteggio cambia.

using Godot;
using System;

public partial class GameManager : Node
{
    // Definizione del segnale
    [Signal]
    public delegate void ScoreChangedEventHandler(int newScore);

    private int _score = 0;

    public void AddScore(int amount)
    {
        _score += amount;
        EmitSignal(SignalName.ScoreChanged, _score);
    }
}

Un altro nodo (ad esempio un HUD in Control) può collegarsi a questo segnale in _Ready():

public partial class Hud : Control
{
    private Label _scoreLabel;

    public override void _Ready()
    {
        _scoreLabel = GetNode<Label>("ScoreLabel");
        var gameManager = GetNode<GameManager>("../GameManager");

        gameManager.ScoreChanged += OnScoreChanged;
    }

    private void OnScoreChanged(int newScore)
    {
        _scoreLabel.Text = $"Punteggio: {newScore}";
    }
}

Questa struttura a segnali è particolarmente utile su Android per tenere separata la logica di gioco dalla UI, che può cambiare in base al device (smartphone, tablet, TV).

11. Esempio completo: pulsante touch che aggiorna una Label

Ricapitoliamo l’esempio principale con una struttura di scena chiara e uno script completo pronto per Android.

11.1 Struttura della scena

Scene: res://Scenes/Main.tscn

  • Main (Node2D)
    • UIRoot (Control)
      • StatusLabel (Label)
      • TapButton (Button)

11.2 Script C# completo

using Godot;
using System;

public partial class Main : Node2D
{
    private Label _statusLabel;
    private Button _tapButton;
    private int _tapCount = 0;

    public override void _Ready()
    {
        // Recupero dei riferimenti ai nodi UI
        _statusLabel = GetNode<Label>("UIRoot/StatusLabel");
        _tapButton = GetNode<Button>("UIRoot/TapButton");

        // Inizializza il testo
        _statusLabel.Text = "Tocca il pulsante per iniziare";

        // Imposta il testo del pulsante (opzionale)
        _tapButton.Text = "Tocca qui";

        // Collega il segnale pressed del pulsante
        _tapButton.Pressed += OnTapButtonPressed;
    }

    public override void _Process(double delta)
    {
        // Nessuna logica per frame in questo esempio
        // Qui potresti aggiungere animazioni o timer
    }

    private void OnTapButtonPressed()
    {
        // Metodo chiamato quando l'utente tocca il pulsante su Android
        _tapCount++;

        _statusLabel.Text = $"Pulsante toccato {_tapCount} volta(e)!";

        GD.Print($"[Android] Tap #{_tapCount}");
    }
}

Questo codice è pensato per funzionare sia nel Play interno di Godot che su emulatore e dispositivo Android reale, senza modifiche.

12. Test su emulatore e dispositivo Android

12.1 Test rapido su emulatore Android

  • Avvia l’emulatore Android (tramite l’AVD Manager di Android Studio o tool equivalente).
  • In Godot, apri Project > Export e seleziona il preset Android.
  • Imposta il package name e le opzioni minime richieste (già descritte nelle guide precedenti).
  • Clicca su Export & Run (se disponibile) o esporta l’APK e installalo manualmente sull’emulatore.

Controlla che il pulsante sia facilmente cliccabile anche con input del mouse, simulando il touch.

12.2 Test su dispositivo Android reale

  • Attiva le Opzioni sviluppatore sul dispositivo e abilita il Debug USB.
  • Collega il dispositivo al PC via USB e verifica che sia riconosciuto (tramite adb devices o strumenti equivalenti).
  • Esporta e installa l’APK, oppure utilizza le funzioni di deploy diretto di Godot se configurate.

Verifica che:

  • La Label sia leggibile (testo abbastanza grande).
  • Il Button sia facilmente toccabile (dimensione e margini adeguati).
  • La UI non venga tagliata su dispositivi con notch o proporzioni insolite.

13. Consigli per principianti

  • Nomina bene i nodi: evita nomi generici come Node2D2, usa nomi descrittivi (es. UIRoot, ScoreLabel).
  • Mantieni la scena semplice: all’inizio lavora con poche scene e nodi. Più avanti potrai modularizzare.
  • Usa il debugger di Godot: se la Label non si aggiorna su Android, controlla la console di Godot per eventuali errori di percorso (GetNode).
  • Testa spesso su dispositivo: l’input touch reale può comportarsi in modo diverso rispetto al mouse nel PC.

14. Sezione avanzata: riuso delle scene e ciclo di vita

14.1 Riuso delle scene tramite istanziazione

Un punto di forza di Godot è la possibilità di riutilizzare scene come fossero componenti. Per esempio, puoi creare una scena ButtonPanel.tscn con un gruppo di pulsanti già configurati per Android e istanziarla in più parti del tuo gioco.

public partial class Main : Node2D
{
    public PackedScene ButtonPanelScene;

    public override void _Ready()
    {
        // Carica la scena da istanziare
        ButtonPanelScene = GD.Load<PackedScene>("res://Scenes/ButtonPanel.tscn");

        // Istanzia la scena a runtime
        var panelInstance = ButtonPanelScene.Instantiate<Control>();

        // Aggiungi il pannello UI come figlio di UIRoot
        var uiRoot = GetNode<Control>("UIRoot");
        uiRoot.AddChild(panelInstance);
    }
}

In questo modo puoi mantenere componenti UI consistenti tra più scene, facilitando manutenzione e localizzazione (importante per app Android internazionali).

14.2 Ciclo di vita della scena su Android

Su Android l’app può essere sospesa, messa in background e ripresa. Godot gestisce buona parte di questo ciclo di vita per te, ma è utile conoscere alcuni metodi:

  • _EnterTree(): chiamato quando il nodo entra nell’albero della scena.
  • _Ready(): chiamato quando il nodo è pronto (dopo _EnterTree).
  • _ExitTree(): chiamato quando il nodo esce dall’albero della scena.

Per gestire correttamente lo stato (es. pausa del gioco quando l’utente minimizza l’app), puoi combinare i metodi di ciclo di vita di Godot con la gestione della pausa (GetTree().Paused = true;) e, se necessario, ascoltare eventi specifici dell’ambiente Android tramite moduli dedicati (che vedremo in articoli successivi).

15. Errori comuni e come evitarli

  • GetNode che restituisce errore: spesso dovuto a percorsi errati o a rinomina dei nodi dopo aver scritto il codice. Verifica la gerarchia e aggiorna le stringhe "UIRoot/StatusLabel", ecc.
  • Script C# non compilato: se vedi errori di compilazione, esegui un build completo del progetto dalla tab Script o controlla il tuo IDE esterno.
  • UI troppo piccola su Android: ricordati di testare su più densità e di usare font e pulsanti sufficientemente grandi.
  • Logica messa nel costruttore invece che in _Ready: sposta il codice che accede a nodi o risorse in _Ready() per evitare null reference.

16. FAQ rapide

  • D: Posso usare Node al posto di Node2D?
    R: Sì, se non ti serve una rappresentazione 2D (posizione, rotazione, ecc.). Per la maggior parte dei giochi 2D è più comodo partire da Node2D.
  • D: Devo sempre usare i segnali?
    R: No, ma sono il modo consigliato per far comunicare nodi diversi senza creare dipendenze rigide, soprattutto in progetti Android più grandi.
  • D: È meglio collegare i segnali da editor o da codice C#?
    R: Per piccole scene l’editor è comodo; per progetti medio-grandi e versionati (Git, ecc.) è spesso preferibile collegarli da codice per avere tutto esplicito.
  • D: Come organizzo le scene per un gioco Android con molti livelli?
    R: In genere conviene avere una scena principale che gestisce il flusso (menù, caricamento livelli) e scene separate per ogni livello, più scene riutilizzabili per HUD e pannelli UI.

17. Riepilogo

In questa bozza abbiamo visto come funzionano scene, nodi e segnali in Godot 4 con C#, applicandoli a un caso concreto: una semplice interfaccia Android con Node2D come root, un Control per la UI, un Button touch e una Label aggiornabile. Hai imparato a usare _Ready() per l’inizializzazione, _Process() per la logica per frame, a collegare segnali integrati e personalizzati, e hai visto come iniziare a riutilizzare scene tramite istanziazione.

18. Anticipazione del prossimo articolo

Nel prossimo articolo della serie “Godot 4 per Android con C#” passeremo dalla teoria alla pratica completa: costruiremo una piccola scena di gioco 2D con input touch (tap e swipe), gestendo il passaggio tra scene (es. menu <-> gioco) e introducendo i primi elementi di salvataggio dati persistenti su Android. Approfondiremo inoltre l’uso dei Control per realizzare HUD adattivi e ottimizzati per diversi form factor.

Commenti

Lascia un commento