エディタでコードを実行する

tool とは何ですか?

`` tool``は強力なコード行で、スクリプトの先頭に追加すると、エディタで実行できるようになります。スクリプトのどの部分をエディタで実行し、どの部分をゲームで実行するか、または両方で実行するかを決定することもできます。

多くの目的のためにそれを使用できますが、レベル設計をするときに、予測が難しいものを視覚的に提示するためにとても役立ちます。使用例は次のとおりです:

  • If you have a cannon that shoots cannonballs affected by physics (gravity), you can draw the cannonball's trajectory in the editor, making level design a lot easier.
  • ジャンプの高さが異なるジャンプパッドがある場合、プレイヤーがジャンプした場合に到達する最大ジャンプ高を描画でき、レベル設計も容易になります。
  • プレイヤーがスプライトを使用せず、コードを使用して描画を行う場合に、エディタでその描画コードを実行してプレイヤーを表示できます。

危険

tool スクリプトはエディタ内で実行され、現在編集されているシーンのシーンツリーにアクセスできます。エディタには tool スクリプトの潜在的な誤用に対する保護が含まれていないため、これは警告も伴う強力な機能です。特に Node.queue_free を介してシーンツリーを操作するときは、エディタがそれに関連するロジックを実行している間にノードを解放するとクラッシュする可能性があるため、非常に注意してください。

使用方法

To turn a script into a tool, add the keyword tool at the top of your code.

現在エディタで実行されているかどうかを確認するには、Engine.editor_hint を使用します。

For example, if you want to execute some code only in the editor, use:

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

On the other hand, if you want to execute code only in game, simply negate the same statement:

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

Pieces of code do not have either of the 2 conditions above will run both in-editor and in-game.

Here is how a _process() function might look for you:

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.
}

注釈

Modifications in editor are permanent. For example, in the following case, when we remove the script, the node will keep its rotation. Be careful to avoid making unwanted modifications.

やってみましょう

シーンに Sprite ノードを追加し、テクスチャをGodotアイコンに設定します。スクリプトをアタッチして開き、次の手順に変更します:

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;
    }
}

スクリプトを保存して、エディタに戻ります。これで、オブジェクトが回転するのが見えるはずです。ゲームを実行すると、ゲームも回転します。

../../_images/rotating_in_editor.gif

注釈

変更が表示されない場合は、シーンをリロードします(閉じてからもう一度開きます)。

次に、どのコードがいつ実行されるのかを選択しましょう。_process() 関数を次のように変更します:

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;
    }
}

スクリプトを保存します。これで、オブジェクトはエディタでは時計回りに回転しますが、ゲームを実行すると、反時計回りに回転します。

Editing variables

Add and export a variable speed to the script. The function set_speed after "setget" is executed with your input to change the variable. Modify _process() to include the rotation speed.

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;
    }
}

注釈

他のノードからのコードはエディタで実行されません。他のノードへのアクセスは制限されています。ツリーとノード、およびそれらのデフォルトのプロパティにはアクセスできますが、ユーザー変数にはアクセスできません。そうしたい場合は、他のノードもエディタで実行する必要があります。 AutoLoadノードにはエディタではまったくアクセスできません。

シーンのインスタンス化

You can instantiate packed scenes normally and add them to the scene currently opened in the editor. Be sure to set the scene root as the owner of all the nodes created this way or the nodes won't be visible in the editor.

If you are using tool:

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;
}

If you are using EditorScript:

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();
}

警告

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.