Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

シーンとスクリプトを使用する場合

シーンとスクリプトの違いについてはすでに説明しました。スクリプトは、命令型コードでエンジンクラスの拡張を定義し、宣言型コードでシーンを定義します。

Each system's capabilities are different as a result. Scenes can define how an extended class initializes, but not what its behavior actually is. Scenes are often used in conjunction with a script, the scene declaring a composition of nodes, and the script adding behaviour with imperative code.

匿名型

スクリプトのみを使用してシーンのコンテンツを完全に定義することもできます。これは本質的にはGodotエディタで行うべきことですが、スクリプトで行う場合はそのオブジェクトのC++コンストラクターで行います。

しかし、どちらを使用するかを選択することはジレンマになる可能性があります。スクリプトインスタンスの作成はエンジン内クラスの作成と同じですが、シーンの処理にはAPIを変更する必要があります:

const MyNode = preload("my_node.gd")
const MyScene = preload("my_scene.tscn")
var node = Node.new()
var my_node = MyNode.new() # Same method call.
var my_scene = MyScene.instantiate() # Different method call.
var my_inherited_scene = MyScene.instantiate(PackedScene.GEN_EDIT_STATE_MAIN) # Create scene inheriting from MyScene.

また、エンジンとスクリプトコードの処理速度が異なるため、スクリプトの動作はシーンよりも少し遅くなります。ノードが大きく複雑になるほど、ノードをシーンとして構築する理由が増えます。

名前付き型

Scripts can be registered as a new type within the editor itself. This displays it as a new type in the node or resource creation dialog with an optional icon. This way, the user's ability to use the script is much more streamlined. Rather than having to...

  1. 使用するスクリプトの基本型を知っている。

  2. その基本型のインスタンスを作成します。

  3. ノードにスクリプトを追加します。

With a registered script, the scripted type instead becomes a creation option like the other nodes and resources in the system. The creation dialog even has a search bar to look up the type by name.

There are two systems for registering types:

  • カスタム型

    • エディタのみ。型名は実行時にはアクセスできません。

    • 継承されたカスタム型はサポートされていません。

    • 初期化ツール。スクリプトを使用してノードを作成します。これ以外の方法はありません。

    • エディタは、スクリプトの型や、他のエンジン内の型やスクリプトとの関係を認識しません。

    • ユーザーがアイコンを定義できます。

    • スクリプトリソースを抽象化して扱うので、すべてのスクリプト言語で動作します。

    • EditorPlugin.add_custom_type を使用してセットアップします。

  • Script Classes

    • エディタとランタイムにアクセスできます。

    • 継承関係を完全に表示します。

    • スクリプトを使用してノードを作成しますが、エディタから型を変更したり、型を拡張したりすることもできます。

    • エディタは、スクリプト、スクリプトクラス、およびエンジンのC++クラス間の継承関係を認識します。

    • ユーザーがアイコンを定義できます。

    • エンジン開発者は、言語のサポートを手動で追加する必要があります(名前の公開とランタイムのアクセシビリティの両方)。

    • Godot3.1以降のみです。

    • エディタは、プロジェクトフォルダをスキャンし、すべてのスクリプト言語の公開名を登録します。各スクリプト言語は、この情報を公開するための独自のサポートを実装する必要があります。

どちらの方法でも作成ダイアログに名前が追加されますが、特にスクリプト クラスを使用すると、ユーザーはスクリプト リソースを読み込まずに型名にアクセスできます。インスタンスの作成と定数または静的メソッドへのアクセスは、どこからでも実行可能です。

このような機能を使用すると、それによってユーザーに付与される使いやすさから、その型をシーンのないスクリプトにしたい場合があります。このようにプラグインを開発したり、デザイナーが使用する社内ツールを作成したりすることで、物事をより簡単な手順で進められるようになります。

欠点として、大部分が命令型プログラミングを使用する必要があることも意味します。

Performance of Script vs PackedScene

One last aspect to consider when choosing scenes and scripts is execution speed.

As the size of objects increases, the scripts' necessary size to create and initialize them grows much larger. Creating node hierarchies demonstrates this. Each Node's logic could be several hundred lines of code in length.

The code example below creates a new Node, changes its name, assigns a script to it, sets its future parent as its owner so it gets saved to disk along with it, and finally adds it as a child of the Main node:

# main.gd
extends Node

func _init():
    var child = Node.new()
    child.name = "Child"
    child.script = preload("child.gd")
    add_child(child)
    child.owner = self

Script code like this is much slower than engine-side C++ code. Each instruction makes a call to the scripting API which leads to many "lookups" on the back-end to find the logic to execute.

Scenes help to avoid this performance issue. PackedScene, the base type that scenes inherit from, defines resources that use serialized data to create objects. The engine can process scenes in batches on the back-end and provide much better performance than scripts.

結論

最後に、最善のアプローチは次のことを考慮することです。

  • いくつかの異なるプロジェクトで再利用され、すべてのスキルレベルの人々(自分自身を「プログラマー」とラベル付けしない人を含む)が使用する可能性のある基本的なツールを作成したい場合、それは良い機会であり、おそらくスクリプトで作成する必要があります。また、カスタム名/アイコンが付いたものでなければなりません。

  • ゲームに特化したコンセプト(モデル)を作りたい場合は、常にシーンである必要があります。シーンは追跡/編集が容易で、スクリプトよりもセキュリティが強化されます。

  • If one would like to give a name to a scene, then they can still sort of do this by declaring a script class and giving it a scene as a constant. The script becomes, in effect, a namespace:

    # game.gd
    class_name Game # extends RefCounted, so it won't show up in the node creation dialog.
    extends RefCounted
    
    const MyScene = preload("my_scene.tscn")
    
    # main.gd
    extends Node
    func _ready():
        add_child(Game.MyScene.instantiate())