Code im Editor ausführen

Was ist tool?

tool ist eine leistungsstarke Codezeile, die im Editor ausgeführt wird, wenn man sie oben im Skript hinzufügt. Sie können auch entscheiden, welche Teile des Skripts im Editor ausgeführt werden, welche im Spiel und welche in beiden.

Sie können es für viele Dinge verwenden, aber es ist vor allem im Level-Design nützlich, um Dinge visuell darzustellen, die selbst schwer vorherzusagen sind. Hier sind einige Anwendungsfälle:

  • Wenn Sie eine Kanone haben, die physikalisch (Schwerkraft) korrekte Kanonenkugeln abschießt, können Sie die Flugbahn der Kanonenkugel im Editor zeichnen, was das Level-Design erheblich vereinfacht.
  • Wenn Sie auf Ihrem Joypad Sprungtasten mit unterschiedlichen Sprunghöhen haben, können Sie die maximale Sprunghöhe zeichnen die ein Spieler erreichen würde, was auch das Level-Design erleichtert.
  • Wenn Ihr Spieler kein Sprite verwendet, sondern durch Code gezeichnet wird, können Sie diesen Zeichencode im Editor ausführen lassen, um Ihren Spieler anzuzeigen.

Gefahr

tool scripts run inside the editor, and let you access the scene tree of the currently edited scene. This is a powerful feature which also comes with caveats, as the editor does not include protections for potential misuse of tool scripts. Be extremely cautious when manipulating the scene tree, especially via Node.queue_free, as it can cause crashes if you free a node while the editor runs logic involving it.

Wie man es benutzt

Um ein Skript in ein Tool zu verwandeln, fügen Sie das Schlüsselwort tool oben in Ihren Code ein.

Um zu überprüfen ob Sie sich gerade im Editor befinden, verwenden Sie: Engine.editor_hint.

Wenn Sie beispielsweise Code nur im Editor ausführen möchten, verwenden Sie:

if Engine.editor_hint:
    # Code to execute when in editor.
if (Engine.EditorHint)
{
    // Code to execute when in editor.
}

Wenn Sie dagegen Code nur im Spiel ausführen möchten, negieren Sie einfach dieselbe Aussage:

if not Engine.editor_hint:
    # Code to execute when in game.
if (!Engine.EditorHint)
{
    // Code to execute when in game.
}

Code-Teile, die keine der beiden oben genannten Bedingungen haben, werden sowohl im Editor als auch im Spiel ausgeführt.

Hier sieht man wie eine _process() Funktion aussehen könnte:

func _process(delta):
    if Engine.editor_hint:
        # Code to execute in editor.

    if not Engine.editor_hint:
        # Code to execute in game.

    # Code to execute both in editor and in game.
public override void _Process(float delta)
{
    if (Engine.EditorHint)
    {
        // Code to execute in editor.
    }

    if (!Engine.EditorHint)
    {
        // Code to execute in game.
    }

    // Code to execute both in editor and in game.
}

Bemerkung

Änderungen im Editor sind dauerhaft. Wenn wir beispielsweise im folgenden Fall das Skript entfernen, behält der Node seine Rotation bei. Vermeiden Sie unerwünschte Änderungen.

Probieren Sie es aus

Fügen Sie Ihrer Szene einen Sprite-Node hinzu und setzen Sie die Textur auf das Godot-Symbol. Hängen Sie ein Skript an, öffnen Sie es und ändern Sie es in Folgendes:

tool
extends Sprite

func _process(delta):
    rotation_degrees += 180 * delta
using Godot;
using System;

[Tool]
public class MySprite : Sprite
{
    public override void _Process(float delta)
    {
        RotationDegrees += 180 * delta;
    }
}

Speichern Sie das Skript und kehren Sie zum Editor zurück. Sie sollten jetzt sehen wie sich Ihr Objekt dreht. Wenn Sie das Spiel ausführen dreht es sich ebenfalls.

../../_images/rotating_in_editor.gif

Bemerkung

Wenn Sie die Änderungen nicht sehen, laden Sie die Szene neu (schließen Sie sie und öffnen sie erneut).

Wählen wir nun aus welcher Code wann ausgeführt wird. Ändern Sie Ihre ``_process () `` Funktion so ab:

func _process(delta):
    if Engine.editor_hint:
        rotation_degrees += 180 * delta
    else:
        rotation_degrees -= 180 * delta
public override void _Process(float delta)
{
    if (Engine.EditorHint)
    {
        RotationDegrees += 180 * delta;
    }
    else
    {
        RotationDegrees -= 180 * delta;
    }
}

Speichern Sie das Skript. Jetzt dreht sich das Objekt im Editor im Uhrzeigersinn, aber wenn Sie das Spiel ausführen, dreht es sich gegen den Uhrzeigersinn.

Variablen bearbeiten

Fügen Sie dem Skript eine variable Geschwindigkeit hinzu und exportieren Sie sie. Die Funktion set_speed nach "setget" wird mit Ihrer Eingabe ausgeführt um die Variable zu ändern. Ändern Sie _process() um die Drehzahl aufzunehmen.

tool
extends Sprite


export var speed = 1 setget set_speed


# Update speed and reset the rotation.
func set_speed(new_speed):
    speed = new_speed
    rotation_degrees = 0


func _process(delta):
    rotation_degrees += 180 * delta * speed
using Godot;
using System;

[Tool]
public class MySprite : Sprite
{
    private float speed = 1;

    [Export]
    public float Speed {
        get => speed;
        set => SetSpeed(value);
    }

    // Update speed and reset the rotation.
    private void SetSpeed(float newSpeed)
    {
        speed = newSpeed;
        RotationDegrees = 0;
    }

    public override void _Process(float delta)
    {
        RotationDegrees += 180 * delta * speed;
    }
}

Bemerkung

Code von anderen Nodes wird nicht im Editor ausgeführt. Ihr Zugriff auf andere Nodes ist eingeschränkt, Sie können damit auf den Baum und die Nodes sowie deren Standardeigenschaften zugreifen, jedoch nicht auf Benutzervariablen. Wenn Sie dies möchten, müssen auch andere Nodes im Editor ausgeführt werden. Auf AutoLoad-Nodes kann im Editor überhaupt nicht zugegriffen werden.

Szenen in­s­tan­zi­ie­ren

Sie können gepackte Szenen normal instanziieren und zu der aktuell im Editor geöffneten Szene hinzufügen. Stellen Sie sicher, dass Sie die Szenenwurzel als Eigentümer aller auf diese Weise erstellten Nodes festlegen, da sonst die Nodes im Editor nicht sichtbar sind.

Wenn Sie tool verwenden:

func _ready():
    var node = Spatial.new()
    add_child(node) # Parent could be any node in the scene
    node.set_owner(get_tree().edited_scene_root)
public override void _Ready()
{
    var node = new Spatial();
    AddChild(node); // Parent could be any node in the scene
    node.Owner = GetTree().EditedSceneRoot;
}

Wenn Sie EditorScript verwenden:

func _run():
    var parent = get_scene().find_node("Parent") # Parent could be any node in the scene
    var node = Spatial.new()
    parent.add_child(node)
    node.set_owner(get_scene())
public override void _Run()
{
    var parent = GetScene().FindNode("Parent"); // Parent could be any node in the scene
    var node = new Spatial();
    parent.AddChild(node);
    node.Owner = GetScene();
}

Warnung

Using tool improperly can yield many errors. It is advised to first write the code how you want it, and only then add the tool keyword to the top. Also, make sure to separate code that runs in-editor from code that runs in-game. This way, you can find bugs more easily.