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
Instantiating nodes that render anything in 2D or 3D (such as Sprite2D or MeshInstance3D) is not thread-safe by default. To run the rendering driver on a separate thread, set the Rendering > Driver > Thread Model project setting to 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
Modifying a unique resource from multiple threads is not supported. However, handling references on multiple threads is supported. Hence loading resources on a thread is, as well. Scenes, textures, meshes, etc. can be loaded and manipulated on a thread and then added to the active scene on the main thread. The limitation here is as described above: one must be careful not to load the same resource from multiple threads at once. Therefore, it's easiest to use one thread for loading and modifying resources, and then the main thread for adding them.