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.

Proprietà esportate in C#

In Godot, è possibile esportare i membri di una classe. Ciò significa che il loro valore è salvato insieme alla risorsa (ad esempio, scene) a cui sono associati. Saranno anche disponibili per la modifica nell'editor delle proprietà. L'esportazione avviene tramite l'attributo [Export].

using Godot;

public partial class ExportExample : Node3D
{
    [Export]
    public int Number { get; set; } = 5;
}

Nell'esempio precedente il valore 5 sarà salvato e, dopo aver compilato il progetto attuale, sarà visibile nell'editor delle proprietà.

Uno dei motivi fondamentali per esportare variabili membro è per renderle visibili e modificabili nell'editor. Facendo così, artisti e game designer possono modificare valori che poi influiranno sull'esecuzione del programma. A questo scopo, viene fornita una sintassi di esportazione specifica.

L'esportazione si può effettuare solo con Tipi compatibili con Variant.

Nota

È possibile esportare proprietà anche in GDScript; per informazioni al riguardo, consultare Proprietà esportate in GDScript.

Utilizzo di base

L'esportazione funziona con campi e proprietà. Possono avere qualsiasi modificatore di accesso.

[Export]
private int _number;

[Export]
public int Number { get; set; }

I membri esportati possono specificare un valore predefinito; se non, viene utilizzato il valore predefinito del tipo.

Un int come Number ha come valore predefinito 0. Text ha come valore predefinito null perché string è un tipo di riferimento.

[Export]
public int Number { get; set; }

[Export]
public string Text { get; set; }

È possibile specificare valori predefiniti per campi e proprietà.

[Export]
private string _greeting = "Hello World";

[Export]
public string Greeting { get; set; } = "Hello World";

Le proprietà con un campo sottostante utilizzano il valore predefinito del campo sottostante.

private int _number = 2;

[Export]
public int NumberWithBackingField
{
    get => _number;
    set => _number = value;
}

Nota

Il metodo get di una proprietà non viene proprio eseguito per determinare il valore predefinito. Godot analizza invece il codice sorgente C#. Ciò funziona correttamente quasi sempre, come negli esempi di questa pagina. Tuttavia, alcune proprietà sono troppo complesse da interpretare per l'analizzatore.

Ad esempio, la seguente proprietà tenta di utilizzare la matematica per visualizzare il valore predefinito come 5 nell'editor delle proprietà, ma non funziona:

[Export]
public int NumberWithBackingField
{
    get => _number + 3;
    set => _number = value - 3;
}

private int _number = 2;

L'analizzatore non riesce a interpretare questo codice e ricorre al valore predefinito per int, 0. Tuttavia, quando si esegue la scena o si ispeziona un nodo con uno script tool allegato, _number sarà 2 e NumberWithBackingField restituirà 5. Questa differenza potrebbe essere confusionaria. Per evitare ciò, non utilizzare proprietà complesse. Altrimenti, se il valore predefinito si può specificare esplicitamente, si può sovrascrivere con i metodi _PropertyCanRevert() e _PropertyGetRevert().

È possibile esportare qualsiasi tipo di Resource o Node. L'editor delle proprietà mostra una finestra di dialogo di assegnazione intuitiva per questi tipi. Questa si può utilizzare al posto di GD.Load e GetNode. Consultare Nodi e Risorse.

[Export]
public PackedScene PackedScene { get; set; }

[Export]
public RigidBody2D RigidBody2D { get; set; }

Raggruppare le esportazioni

È possibile raggruppare le proprietà esportate all'interno dell'Ispettore con l'attributo [ExportGroup]. Ogni proprietà esportata dopo questo attributo sarà aggiunta al gruppo. Creare un nuovo gruppo o usare [ExportGroup("")] per separare tra gruppi.

[ExportGroup("My Properties")]
[Export]
public int Number { get; set; } = 3;

Il secondo argomento dell'attributo serve per raggruppare solo le proprietà con il prefisso specificato.

I gruppi non si possono annidare, usare [ExportSubgroup] per creare sottogruppi all'interno di un gruppo.

[ExportSubgroup("Extra Properties")]
[Export]
public string Text { get; set; } = "";
[Export]
public bool Flag { get; set; } = false;

È possibile anche cambiare il nome della categoria principale o creare categorie aggiuntive nell'elenco delle proprietà con l'attributo [ExportCategory].

[ExportCategory("Main Category")]
[Export]
public int Number { get; set; } = 3;
[Export]
public string Text { get; set; } = "";

[ExportCategory("Extra Category")]
[Export]
public bool Flag { get; set; } = false;

Nota

L'elenco delle proprietà è organizzato in base all'ereditarietà delle classi e l'aggiunta di nuove categorie non rispetta questa convenzione. Da usare con cautela, soprattutto quando si creano progetti per uso pubblico.

Stringhe rappresentanti percorsi

È possibile utilizzare le indicazioni sulle proprietà per esportare stringhe come percorsi

Stringa rappresentante un percorso a un file.

[Export(PropertyHint.File)]
public string GameFile { get; set; }

Stringa come percorso a una cartella.

[Export(PropertyHint.Dir)]
public string GameDirectory { get; set; }

Stringa come percorso a una file, filtro personalizzato fornito come indicazione.

[Export(PropertyHint.File, "*.txt,")]
public string GameFile { get; set; }

È possibile utilizzare anche i percorsi nel file system globale, ma solo negli script in modalità strumento (tool).

Stringa come percorso a un file PNG nel file system globale.

[Export(PropertyHint.GlobalFile, "*.png")]
public string ToolImage { get; set; }

Stringa come percorso a una cartella nel file system globale.

[Export(PropertyHint.GlobalDir)]
public string ToolDir { get; set; }

L'annotazione multilinea indica all'editor di mostrare un ampio campo di input per la modifica su più righe.

[Export(PropertyHint.MultilineText)]
public string Text { get; set; }

Limitare gli intervalli inseribili nell'editor

Utilizzando l'indicazione di proprietà di intervallo è possibile limitare ciò che si può inserire come valore nell'editor.

Permette valori interi da 0 a 20.

[Export(PropertyHint.Range, "0,20,")]
public int Number { get; set; }

Permette valori interi da -10 a 20.

[Export(PropertyHint.Range, "-10,20,")]
public int Number { get; set; }

Permette valori in virgola mobile da -10 a 20 e aggancia il valore a multipli di 0,2.

[Export(PropertyHint.Range, "-10,20,0.2")]
public float Number { get; set; }

Se si aggiungono le indicazioni "or_greater" e/o "or_less" è possibile andare sopra o sotto i limiti se si digita il valore anziché usare lo slider.

[Export(PropertyHint.Range, "0,100,1,or_greater,or_less")]
public int Number { get; set; }

Numeri in virgola mobile con indicazione di easing

Visualizza una rappresentazione visiva della funzione ease durante la modifica.

[Export(PropertyHint.ExpEasing)]
public float TransitionSpeed { get; set; }

Esporta con indicazione di suffisso

Visualizza un suffisso di unità per le variabili esportate. Funziona con tipi numerici, come float o vettori:

[Export(PropertyHint.None, "suffix:m/s\u00b2")]
public float Gravity { get; set; } = 9.8f;
[Export(PropertyHint.None, "suffix:m/s")]
public Vector3 Velocity { get; set; }

Nell'esempio sopra, \u00b2 è utilizzato per scrivere il carattere "al quadrato" (²).

Colori

Colore regolare fornito come valore rosso-verde-blu-alfa.

[Export]
public Color Color { get; set; }

Colore fornito come valore rosso-verde-blu (alfa sarà sempre 1).

[Export(PropertyHint.ColorNoAlpha)]
public Color Color { get; set; }

Nodi

È possibile anche esportare i nodi direttamente senza dover utilizzare NodePath.

[Export]
public Node Node { get; set; }

È anche possibile esportare direttamente un tipo specifico di nodo. L'elenco dei nodi visualizzato dopo aver premuto "Assegna" nell'ispettore è filtrato in base al tipo specificato e solo un nodo corretto può essere assegnato.

[Export]
public Sprite2D Sprite2D { get; set; }

È possibile esportare le classi di nodi personalizzate direttamente. Il comportamento del filtro dipende dal fatto che la classe personalizzata sia una classe globale.

È ancora possibile esportare i NodePath come in Godot 3.x, nel caso in cui sia necessario:

[Export]
public NodePath NodePath { get; set; }

public override void _Ready()
{
    var node = GetNode(NodePath);
}

Risorse

[Export]
public Resource Resource { get; set; }

Nell'Ispettore, sarà quindi possibile trascinare e rilasciare un file di risorse dal pannello del FileSystem nello slot della variabile.

Tuttavia, l'apertura del menu a discesa dell'ispettore potrebbe risultare in un elenco estremamente lungo di possibili classi da creare. Pertanto, se si specifica un tipo derivato da Resource come:

[Export]
public AnimationNode AnimationNode { get; set; }

Il menu a discesa sarà limitato ad AnimationNode e a tutte le sue classi derivate. È possibile utilizzare anche le classi di risorse personalizzate, consultare Classi globali in C#.

È importante notare che anche se lo script non si sta eseguendo nell'editor, le proprietà esportate sono comunque modificabili. Ciò può servire in combinazione con uno script in modalità "strumento" (tool).

Esportare bit flag

È possibile esportare i membri il cui tipo è un enumerazione con l'attributo [Flags] e i loro valori sono limitati ai membri dell'enumerazione. L'editor creerà un widget nell'Ispettore, consentendo di selezionare nessuno, uno o più membri dell'enumerazione. Il valore sarà memorizzato come numero intero.

Un enumerazione di flag utilizza potenze di 2 per i valori dei membri dell'enumerazione. Sono possibili anche membri che combinano più flag tramite OR logici (|).

[Flags]
public enum SpellElements
{
    Fire = 1 << 1,
    Water = 1 << 2,
    Earth = 1 << 3,
    Wind = 1 << 4,

    FireAndWater = Fire | Water,
}

[Export]
public SpellElements MySpellElements { get; set; }

Gli interi utilizzati come bit flag possono memorizzare più valori true/false (booleani) in un'unica proprietà. Utilizzando l'indicazione di proprietà Flags, è possibile impostare dall'editor uno qualsiasi dei flag specificati.

[Export(PropertyHint.Flags, "Fire,Water,Earth,Wind")]
public int SpellElements { get; set; } = 0;

È necessario fornire una descrizione sotto forma di stringa per ogni flag. In questo esempio, Fire ha il valore 1, Water ha il valore 2, Earth ha il valore 4 e Wind corrisponde al valore 8. Di solito, le costanti si dovrebbero definire di conseguenza (ad esempio private const int ElementWind = 8 e così via).

È possibile aggiungere valori espliciti utilizzando i due punti:

[Export(PropertyHint.Flags, "Self:4,Allies:8,Foes:16")]
public int SpellTargets { get; set; } = 0;

Solo i valori che sono potenze di 2 sono validi come opzioni di bit flag. Il valore minimo consentito è 1, poiché 0 indica che nulla è selezionato. È anche possibile aggiungere opzioni che sono una combinazione di altri flag:

[Export(PropertyHint.Flags, "Self:4,Allies:8,Self and Allies:12,Foes:16")]
public int SpellTargets { get; set; } = 0;

Sono inoltre fornite annotazioni di esportazione per gli strati di fisica e di rendering definiti nelle impostazioni del progetto.

[Export(PropertyHint.Layers2DPhysics)]
public uint Layers2DPhysics { get; set; }
[Export(PropertyHint.Layers2DRender)]
public uint Layers2DRender { get; set; }
[Export(PropertyHint.Layers3DPhysics)]
public uint Layers3DPhysics { get; set; }
[Export(PropertyHint.Layers3DRender)]
public uint Layers3DRender { get; set; }

L'utilizzo dei bit flag richiede una certa conoscenza delle operazioni bit a bit. In casi di dubbio, utilizzare invece variabili booleane.

Esportare enumerazioni

È possibile esportare i membri il cui tipo è un enumerazione e i loro valori sono limitati ai membri dell'enumerazione. L'editor creerà un widget nell'Ispettore, enumerando quanto segue come "Thing 1", "Thing 2", "Another Thing". Il valore sarà memorizzato come un numero intero.

public enum MyEnum
{
    Thing1,
    Thing2,
    AnotherThing = -1,
}

[Export]
public MyEnum MyEnumCurrent { get; set; }

È possibile anche limitare i membri di tipo intero e stringa a un elenco specifico di valori attraverso l'annotazione [Export] con l'indicazione PropertyHint.Enum. L'editor creerà un widget nell'Ispettore, enumerando i seguenti valori come Warrior, Magician, Thief. Il valore sarà memorizzato come un intero, corrispondente all'indice dell'opzione selezionata (ad esempio 0, 1 o 2).

[Export(PropertyHint.Enum, "Warrior,Magician,Thief")]
public int CharacterClass { get; set; }

È possibile aggiungere valori espliciti utilizzando i due punti:

[Export(PropertyHint.Enum, "Slow:30,Average:60,Very Fast:200")]
public int CharacterSpeed { get; set; }

Se il tipo è string, il valore sarà memorizzato come stringa.

[Export(PropertyHint.Enum, "Rebecca,Mary,Leah")]
public string CharacterName { get; set; }

Se si desidera impostare un valore iniziale, è necessario specificarlo esplicitamente:

[Export(PropertyHint.Enum, "Rebecca,Mary,Leah")]
public string CharacterName { get; set; } = "Rebecca";

Esportare pulsanti dell'ispettore con [ExportToolButton]

Se è necessario creare un pulsante cliccabile nell'ispettore, è possibile usare l'attributo [ExportToolButton]. Questo esporta una proprietà o un campo Callable come pulsante cliccabile. Poiché ciò è eseguito nell'editor, è obbligatorio utilizzare l'attributo [Tool]. Quando il pulsante viene premuto, il chiamabile viene richiamato:

[Tool]
public partial class MyNode : Node
{
    [ExportToolButton("Click me!")]
    public Callable ClickMeButton => Callable.From(ClickMe);

    public void ClickMe()
    {
        GD.Print("Hello world!");
    }
}

È anche possibile impostare un'icona per il pulsante con un secondo argomento. Se specificato, l'icona sarà recuperata tramite GetThemeIcon(), dal tipo di tema "EditorIcons".

[ExportToolButton("Click me!", Icon = "CharacterBody2D")]
public Callable ClickMeButton => Callable.From(ClickMe);

Esportazione di raccolte

Come spiegato nella documentazione C# Variant, solo alcuni array C# e i tipi di raccolta definiti nello spazio dei nomi Godot.Collections sono compatibili con Variant, pertanto è possibile esportare solo tali tipi.

Esportazione di array di Godot

[Export]
public Godot.Collections.Array Array { get; set; }

Utilizzando il generico Godot.Collections.Array<T> è possibile specificare il tipo degli elementi dell'array, che sarà utilizzato come indicazione per l'editor. L'Ispettore limiterà gli elementi al tipo specificato.

[Export]
public Godot.Collections.Array<string> Array { get; set; }

Il valore predefinito degli array Godot è null. È possibile specificare un valore predefinito diverso:

[Export]
public Godot.Collections.Array<string> CharacterNames { get; set; } =
[
    "Rebecca",
    "Mary",
    "Leah",
];

Gli array con tipi specificati che ereditano da Resource si possono impostare trascinando e rilasciando più file dal pannello FileSystem.

[Export]
public Godot.Collections.Array<Texture> Textures { get; set; }

[Export]
public Godot.Collections.Array<PackedScene> Scenes { get; set; }

Esportazione di dizionari di Godot

[Export]
public Godot.Collections.Dictionary Dictionary { get; set; }

Utilizzando il generico Godot.Collections.Dictionary<TKey, TValue> è possibile specificare i tipi degli elementi chiave e valore del dizionario.

[Export]
public Godot.Collections.Dictionary<string, int> Dictionary { get; set; }

Il valore predefinito dei dizionari Godot è null. È possibile specificare un valore predefinito diverso:

[Export]
public Godot.Collections.Dictionary<string, int> CharacterLives { get; set; } = new Godot.Collections.Dictionary<string, int>
{
    ["Rebecca"] = 10,
    ["Mary"] = 42,
    ["Leah"] = 0,
};

Esportazione di array di C#

È possibile esportare gli array C# a condizione che il tipo degli elementi sia un tipo compatibile con Variant.

[Export]
public Vector3[] Vectors { get; set; }

[Export]
public NodePath[] NodePaths { get; set; }

Il valore predefinito degli array C# è null. È possibile specificare un valore predefinito diverso:

[Export]
public Vector3[] Vectors { get; set; } =
[
    new Vector3(1, 2, 3),
    new Vector3(3, 2, 1),
];

Impostare le variabili esportate da uno script strumento (tool)

Quando si modifica il valore di una variabile esportata da uno script in Modalità strumento (tool), il valore nell'ispettore non verrà aggiornato automaticamente. Per aggiornarlo, è necessario chiamare NotifyPropertyListChanged() dopo aver impostato il valore della variabile esportata.

Esportazioni avanzate

Non sono forniti tutti i tipi di esportazione nel linguaggio stesso, per evitare inutili complessità di progettazione. Di seguito sono descritte alcune funzionalità di esportazione più o meno comuni che si possono implementare con un'API di basso livello.

Prima di proseguire, è opportuno acquisire familiarità con il modo in cui vengono gestite le proprietà e con il modo in cui si possono personalizzare con i metodi _Set(), _Get() e _GetPropertyList(), come descritto in Accedere ai dati o alla logica da un oggetto.

Vedi anche

Per vincolare le proprietà in C++ attraverso i metodi sopra indicati, consultare Vincolare proprietà tramite _set/_get/_get_property_list.

Avvertimento

Lo script deve funzionare in modalità tool affinché i metodi menzionati possano funzionare dall'interno dell'editor.