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...
API thread-safe
Threads
I thread servono per bilanciare la potenza di elaborazione tra CPU e core. Godot supporta il multithreading, ma non nell'intero motore.
Di seguito è riportato un elenco dei modi in cui si può utilizzare il multithreading in diverse aree di Godot.
Ambito globale
La maggior parte dei singleton del Global Scope sono thread-safe di norma. L'accesso ai server dai thread è supportato. Tuttavia, per i server di rendering e di fisica, è necessario prima abilitare il funzionamento thread-safe nelle impostazioni del progetto.
Questo rende i singleton ideali per codice che crea decine di migliaia di istanze nei server e le controlla dai thread. Naturalmente, richiede un po' più di codice, poiché è utilizzato direttamente e non all'interno dell'albero di scene.
Albero di scene
Interagire con l'albero di scene attivo non è thread-safe. Assicurati di utilizzare i mutex quando invii dati tra più thread. Se desideri chiamare funzioni o impostare proprietà da un thread, potresti usare call_deferred o set_deferred:
# Unsafe:
node.add_child(child_node)
# Safe:
node.add_child.call_deferred(child_node)
// Unsafe:
node.AddChild(childNode);
// Safe:
node.CallDeferred(Node.MethodName.AddChild, childNode);
Tuttavia, va bene creare frammenti di scene (nodi disposti ad albero) fuori dall'albero attivo. In questo modo, è possibile creare o istanziare parti di una scena in un thread, per poi aggiungerle al thread principale:
var enemy_scene = load("res://enemy_scene.scn")
var enemy = enemy_scene.instantiate()
enemy.add_child(weapon) # Set a weapon.
world.add_child.call_deferred(enemy)
PackedScene enemyScene = GD.Load<PackedScene>("res://EnemyScene.scn");
Node enemy = enemyScene.Instantiate<Node>();
enemy.AddChild(weapon);
world.CallDeferred(Node.MethodName.AddChild, enemy);
In ogni caso, questo è davvero utile solo se hai un solo thread che carica i dati. Tentare di caricare o creare frammenti di scene dai thread potrebbe funzionare, ma si rischia che le risorse (che in Godot vengono caricate una sola volta) vengano alterate dai vari thread, causando comportamenti imprevisti o arresti anomali.
Utilizza più di un thread per generare i dati delle scene solo se sai davvero cosa stai facendo e sei sicuro che una singola risorsa non sia utilizzata o impostata in più thread. Altrimenti, è più sicuro utilizzare direttamente l'API dei server (che sono completamente thread-safe) e non toccare le scena o le risorse.
Renderer
Istanziare nodi che renderizzano qualcosa in 2D o 3D (come Sprite2D o MeshInstance3D) non è thread-safe normalmente. Per eseguire il driver di rendering su un thread separato, impostare l'impostazione del progetto Rendering > Driver > Thread Model su Separate.
Si noti che il modello di thread Separate ha diversi bug noti, pertanto potrebbe non essere utilizzabile in tutti gli scenari.
Avvertimento
È consigliabile evitare di chiamare funzioni che richiedono di interagire direttamente con la GPU su altri thread, come creare nuove texture o modificare e recuperare dati di immagini. Queste operazioni potrebbero rallentare le prestazioni perché richiedono la sincronizzazione con il RenderingServer, in quanto i dati si devono trasmettere o aggiornare sulla GPU.
Fisica
La simulazione della fisica non è thread-safe normalmente. Per eseguire i server di fisica su thread separati (rendendoli thread-safe), abilitare le seguenti impostazioni del progetto:
PhysicsServer2D: Fisica > 2D > Esegui su thread separato.
PhysicsServer3D: Fisica > 3D > Esegui su thread separato.
Array e dizionari in GDScript
In GDScript, leggere e scrivere elementi da più thread va bene, ma qualsiasi operazione che cambi le dimensioni di un contenitore (ridimensionamento, aggiunta o rimozione di elementi) richiede il blocco di un mutex.
Risorse
Modificare una singola risorsa da più thread non è supportato. Tuttavia, gestire i riferimenti su più thread è supportato. Ecco perché anche caricare le risorse su un thread è supportato: è possibile caricare e manipolare scene, texture, mesh, ecc. su un thread e poi aggiungerle alla scena attiva sul thread principale. La limitazione in questo caso è quella descritta sopra: bisogna fare attenzione a non caricare la stessa risorsa da più thread alla volta. Pertanto, è più semplice utilizzare un solo thread per caricare e modificare le risorse, e poi il thread principale per aggiungerle.