Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Generazione dei mostri
In questa parte, andremo a generare mostri casualmente lungo un percorso. Alla fine, avrete mostri che vagano per il piano di gioco.

Fai doppio clic su main.tscn nel pannello FileSystem per aprire la scena Main.
Prima di disegnare il percorso, cambieremo la risoluzione del gioco. Il nostro gioco ha una dimensione predefinita di finestra di 1152x648. La imposteremo a 720x540, un bel quadratino.
Vai a Progetto -> Impostazioni del progetto.

Se Mappa di input è ancora aperta, passa alla scheda Generale.
Nel menu a sinistra, scorri verso il basso fino a Display -> Finestra. A destra, imposta la Larghezza della viewport a 720 e l''Altezza della viewport a 540.

Creazione del percorso di generazione
Come hai fatto nel tutorial del gioco in 2D, progetterai un percorso e utilizzerai un nodo PathFollow3D per campionare posizioni casuali su di esso.
In 3D, però, disegnare il percorso è un po' più complicato. Vogliamo che circondi la vista di gioco in modo che i mostri appaiano appena fuori dallo schermo. Ma se disegniamo un percorso, non lo vedremo nell'anteprima della telecamera.
Per individuare i limiti della vista, possiamo usare delle mesh segnaposto. La vista dovrebbe comunque essere divisa in due parti, con l'anteprima della telecamera in basso. Se ciò non è il caso, premi Ctrl + 2 (Cmd + 2 su macOS) per dividere la vista in due. Seleziona il nodo Camera3D e clicca sulla casella di spunta Anteprima nella viewport inferiore.

Aggiunta di cilindri segnaposto
Aggiungiamo le mesh segnaposto. Aggiungiamo un nuovo Node3D come nodo figlio del nodo Main e chiamiamolo Cylinders. Lo useremo per raggruppare i cilindri. Selezioniamo Cylinders e aggiungiamo un nodo figlio MeshInstance3D

Nell'Ispettore, assegna un CylinderMesh alla proprietà Mesh.

Imposta la viewport superiore sulla vista ortogonale dall'alto, attraverso il menu nell'angolo in alto a sinistra della viewport. In alternativa, puoi premere il tasto 7 del tastierino numerico.

La griglia potrebbe essere distraente. Puoi alternarla andando al menu Vista nella barra degli strumenti e cliccando su Vedi griglia.

Ora vuoi spostare il cilindro lungo il piano del suolo, osservando l'anteprima della telecamera nella viewport inferiore. Consiglio di usare lo scatto alla griglia. Puoi attivarlo cliccando sull'icona della calamita nella barra degli strumenti o premendo Y.

Sposta il cilindro in modo che si trovi appena fuori dal campo visivo della telecamera, nell'angolo in alto a sinistra.

Creeremo copie della mesh e le posizioneremo nell'area di gioco. Premi Ctrl + D (Cmd + D su macOS) per duplicare il nodo. Puoi anche cliccare con il pulsante destro del mouse sul nodo nel pannello Scena e selezionare Duplica. Sposta la copia verso il basso lungo l'asse Z blu finché non esce dall'anteprima della telecamera.
Seleziona entrambi i cilindri premendo il tasto Maiusc e cliccando su quello non selezionato, quindi duplicali.

Spostali verso destra trascinando l'asse X rosso.

Sono un po' difficili da vedere in bianco, vero? Facciamoli risaltare dandogli un nuovo materiale.
In 3D, i materiali definiscono le proprietà visive di una superficie, come il suo colore, il modo in cui riflette la luce e altro ancora. Possiamo utilizzarli per cambiare il colore di una mesh.
Possiamo aggiornare tutti e quattro i cilindri alla volta. Seleziona tutte le istanze di mesh nel pannello Scena. Per farlo, puoi cliccare sulla prima e cliccare sull'ultima tenendo premuto Maiusc.

Nell'Ispettore, espandi la sezione Material e assegna uno StandardMaterial3D allo slot 0.

Clicca sull'icona a forma di sfera per aprire la risorsa materiale. Otterrai un'anteprima del materiale e un lungo elenco di sezioni pieno di proprietà. Puoi utilizzarle per creare superfici di ogni tipo, dal metallo alla roccia o all'acqua.
Espandi la sezione Albedo.
Imposta il colore su qualcosa che contrasti con lo sfondo, come un arancione brillante.

Ora possiamo utilizzare i cilindri come guide. Riducili nel pannello Scena cliccando sulla freccia grigia accanto a essi. Proseguendo, puoi anche alternarne la visibilità cliccando sull'icona a forma di occhio accanto a Cylinders.

Aggiungi un nodo figlio Path3D al nodo Main. Nella barra degli strumenti compaiono quattro icone. Clicca sullo strumento Aggiungi punto, l'icona con il segno "+" verde.

Nota
È possibile passare il cursore su qualsiasi icona per mostrare una descrizione dello strumento.
Clicca al centro di ogni cilindro per creare un punto. Quindi, clicca sull'icona Chiudi curva nella barra degli strumenti per chiudere il percorso. Se un punto è leggermente fuori asse, puoi cliccare e trascinarlo per riposizionarlo.

Il tuo percorso dovrebbe assomigliare a questo.

Per campionare posizioni casuali sul percorso, abbiamo bisogno di un nodo PathFollow3D. Aggiungi un nodo PathFollow3D come figlio di Path3D. Rinomina i due nodi rispettivamente in SpawnLocation e SpawnPath. Questo descrive meglio a cosa serviranno.

Fatto questo, siamo pronti a programmare il meccanismo di generazione.
Generazione casuale dei mostri
Fai clic destro sul nodo Main e allegaci un nuovo script.
Esportiamo prima una variabile nell'Ispettore in modo da poterle assegnare mob.tscn o qualsiasi altro mostro.
extends Node
@export var mob_scene: PackedScene
using Godot;
public partial class Main : Node
{
// Don't forget to rebuild the project so the editor knows about the new export variable.
[Export]
public PackedScene MobScene { get; set; }
}
Vogliamo generare i mob a intervalli regolari. Per farlo, dobbiamo ritornare alla scena e aggiungere un timer. Prima, però, dobbiamo assegnare il file mob.tscn alla proprietà mob_scene qui sopra (altrimenti è null!)
Torna alla schermata 3D e seleziona il nodo Main. Trascina mob.tscn dal pannello FileSystem allo slot Mob Scene nell'Ispettore.

Aggiungi un nuovo nodo Timer come figlio di Main. Rinominalo MobTimer.

Nell'Ispettore, imposta il suo Wait Time su 0.5 secondi e attiva l'Autostart in modo che si avvii automaticamente quando avviamo il gioco.

I timer emettono un segnale di "timeout" ogni volta che raggiungono la fine del loro tempo di attesa (Wait Time). Come predefinito, si riavviano automaticamente, emettendo il segnale ciclicamente. Possiamo connetterci a questo segnale dal nodo Main per generare mostri ogni 0.5 secondi.
Con il MobTimer ancora selezionato, vai al pannello Segnali sulla destra e fai doppio clic sul segnale timeout.

Collegalo al nodo Main.

Questo ti riporterà allo script, con una nuova funzione vuota _on_mob_timer_timeout().
Programmiamo la logica di generazione dei mob. Andremo a:
Istanziare la scena del mob.
Campionare una posizione casuale sul percorso di generazione.
Recuperare la posizione del giocatore.
Chiamare il metodo
initialize()del mob, passandogli la posizione casuale e la posizione del giocatore.Aggiungere il mob come figlio del nodo Main.
func _on_mob_timer_timeout():
# Create a new instance of the Mob scene.
var mob = mob_scene.instantiate()
# Choose a random location on the SpawnPath.
# We store the reference to the SpawnLocation node.
var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
# And give it a random offset.
mob_spawn_location.progress_ratio = randf()
var player_position = $Player.position
mob.initialize(mob_spawn_location.position, player_position)
# Spawn the mob by adding it to the Main scene.
add_child(mob)
// We also specified this function name in PascalCase in the editor's connection window.
private void OnMobTimerTimeout()
{
// Create a new instance of the Mob scene.
Mob mob = MobScene.Instantiate<Mob>();
// Choose a random location on the SpawnPath.
// We store the reference to the SpawnLocation node.
var mobSpawnLocation = GetNode<PathFollow3D>("SpawnPath/SpawnLocation");
// And give it a random offset.
mobSpawnLocation.ProgressRatio = GD.Randf();
Vector3 playerPosition = GetNode<Player>("Player").Position;
mob.Initialize(mobSpawnLocation.Position, playerPosition);
// Spawn the mob by adding it to the Main scene.
AddChild(mob);
}
Qui sopra, randf() produce un valore casuale compreso tra 0 e 1, che è ciò che il progress_ratio del nodo PathFollow si aspetta: 0 è l'inizio del percorso, 1 è la fine. Il percorso che abbiamo impostato si estende attorno alla viewport della telecamera, quindi qualsiasi valore casuale compreso tra 0 e 1 rappresenta una posizione casuale lungo i bordi della viewport!
Nota che se rimuovi Player dalla scena principale, la seguente riga
var player_position = $Player.position
Vector3 playerPosition = GetNode<Player>("Player").Position;
genera un errore perché non c'è più un $Player!
Ecco lo script main.gd completo fino ad ora, per riferimento.
extends Node
@export var mob_scene: PackedScene
func _on_mob_timer_timeout():
# Create a new instance of the Mob scene.
var mob = mob_scene.instantiate()
# Choose a random location on the SpawnPath.
# We store the reference to the SpawnLocation node.
var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
# And give it a random offset.
mob_spawn_location.progress_ratio = randf()
var player_position = $Player.position
mob.initialize(mob_spawn_location.position, player_position)
# Spawn the mob by adding it to the Main scene.
add_child(mob)
using Godot;
public partial class Main : Node
{
[Export]
public PackedScene MobScene { get; set; }
private void OnMobTimerTimeout()
{
// Create a new instance of the Mob scene.
Mob mob = MobScene.Instantiate<Mob>();
// Choose a random location on the SpawnPath.
// We store the reference to the SpawnLocation node.
var mobSpawnLocation = GetNode<PathFollow3D>("SpawnPath/SpawnLocation");
// And give it a random offset.
mobSpawnLocation.ProgressRatio = GD.Randf();
Vector3 playerPosition = GetNode<Player>("Player").Position;
mob.Initialize(mobSpawnLocation.Position, playerPosition);
// Spawn the mob by adding it to the Main scene.
AddChild(mob);
}
}
Puoi testare la scena premendo F6 (Cmd + R su macOS). Dovresti vedere i mostri apparire e muoversi in linea retta.

Per ora, si scontrano e scivolano l'uno contro l'altro quando i loro percorsi si incrociano. Affronteremo questo problema nella prossima parte.