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...
静的型付けGDScript
このガイドでは、次の内容について学習します:
GDScriptでの静的型付けの使い方;
静的型がバグの回避に役立つこと;
静的型付けにより、エディタのエクスペリエンスが向上します。
この言語機能をどこでどのように使用するかは完全にあなた次第です。一部の機密性の高いGDScriptファイルでのみ使用することも、あらゆる場所で使用することも、まったく使用しないこともできます。
静的型は、変数、定数、関数、パラメーター、戻り値の型に使用できます。
静的型付けの概要
静的型付けのGDScriptを使うことで、Godotはさらに多くのエラーを、あなたの書いたコードから検出することができます。メソッドを呼び出すと引数の型が表示されるため、あなたとチームメイトは作業中により多くの情報が得られます。静的型付けにより、エディタのオートコンプリートとスクリプトの documentation が改善されます。
例えばあなたが在庫管理システムをプログラミングしていると想像してください。まず Item
ノード、次に Inventory
をコーディングします。アイテムをインベントリに追加するには、あなたのコードを操作する人々は常に Item
を Inventory.add()
メソッドに渡すべきだとします。型を設定すれば、これを強制できます:
class_name Inventory
func add(reference: Item, amount: int = 1):
var item := find_item(reference)
if not item:
item = _instance_item_from_db(reference)
item.amount += amount
静的型を使用するとコード補完機能も改善されます。以下に動的型のコードと静的型付きのコードの違いを示します。
あなたはドットを打った後に表示されるオートコンプリート候補が足りないことに遭遇したことがあるでしょう。

これは動的型のコードではGodotエディタは関数にどのような型の値を渡されてくるのかを知ることができません。ただし型を明示的に記述すると、型からすべてのメソッド、プロパティ、定数などを取得することができます。

Tip
静的な型付けを希望する場合は、エディタ設定の テキスト エディター > 自動補完 > 型ヒントの追加 を有効にすることをお勧めします。またデフォルトでは無効になっている いくつかの警告 を有効にすることも検討してください。
また型が指定されたGDScriptは、コンパイル時にオペランドと引数の型がわかっている場合、最適化されたオペコードを使用することでパフォーマンスが向上します。将来的にはJIT/AOTコンパイルなど、さらに多くのGDScriptの最適化が計画されています。
全体として型付きプログラミングはより構造化された経験をあなたに与えます。それはエラーを防いだり、スクリプトをドキュメント化するときに助けになります。これはチームや長期的なプロジェクトで作業している場合に特に効果を発揮します。調査によると他の人が書いたコードを読んだり、過去に自分が書いたスクリプトの内容を思い出すことに、開発者が大半の時間を費やしています。コードが明確で構造化されているほど、素早く理解ができ、素早く前に進むことができます。
静的型付けの使用方法
変数、パラメータ、または定数の型を定義するには、名前の後にコロンを書き、その後に指定する型を書きます。例: var health: int
。 これにより変数の型は常に保持されます:
var damage: float = 10.5
const MOVE_SPEED: float = 50.0
func sum(a: float = 0.0, b: float = 0.0) -> float:
return a + b
コロンを書いて型を省略すると、Godotは型を推測しようとします:
var damage := 10.5
const MOVE_SPEED := 50.0
func sum(a := 0.0, b := 0.0) -> float:
return a + b
注釈
定数の場合、
=
と:=
に違いはありません。Godotは代入された値から自動的に型を設定するため、定数の型ヒントを書く必要はありません。ただしコードの意図をより明確にするために、これを明示的に行うこともできます。また型なし配列がデフォルトで使用されるため、型付き配列 (
const A: Array[int] = [1, 2, 3]
など) を使う場合にも役立ちます。
型ヒント(Type Hint)として使用できるもの
型ヒントとして使用できるものは次のとおりです。
Variant
はAny型。これはほとんどのケースで、型なしの宣言とあまり変わりませんが、可読性は向上します。戻り値の型として使用すると、関数が何らかの値を明示的に返すことを強制できます。(戻り値の型のみ)
void
は関数が値を返さないことを示します。ネイティブクラス (
Object
、Node
、Area2D
、Camera2D
など)。グローバル、ネイティブ、およびカスタムの名前付き列挙型。 列挙型は単なる
int
であり、値が列挙型のセットに属するという保証はないことに注意してください。定数 (ローカルのものを含む)。プリロードされたクラスまたは列挙型が含まれている場合。
カスタムクラスを含む任意のクラスを型として使用できます。スクリプトで使用する方法は2つあります。最初の方法は、定数の型として使用するスクリプトをプリロードすることです:
const Rifle = preload("res://player/weapons/rifle.gd")
var my_rifle: Rifle
2番目の方法は、作成時に class_name
キーワードを使用することです。上記の例では rifle.gd
は次のようになります:
class_name Rifle
extends Node2D
class_name
を使用する場合、Godotは Rifle
型をグローバルにエディタに登録します。定数にプリロードすることなく、どこでも使用できます:
var my_rifle: Rifle
アロー(->
)による関数の戻り値の定義
関数の戻り値の型を定義するには、宣言の後に ->
を記述し、その後に戻り値の型を記述します:
func _process(delta: float) -> void:
pass
void
型は、関数が何も返さないことを意味します。変数と同様に、任意の型を使用できます:
func hit(damage: float) -> bool:
health_points -= damage
return health_points <= 0
独自のクラスを戻り値の型として使用することもできます:
# Adds an item to the inventory and returns it.
func add(reference: Item, amount: int) -> Item:
var item: Item = find_item(reference)
if not item:
item = ItemDatabase.get_instance(reference)
item.amount += amount
return item
共分散と反分散
基本クラスのメソッドを継承するときは、リスコフの置換原則 に従う必要があります。
共分散: メソッドを継承する場合、親メソッドよりも具体的な戻り値の型 (サブタイプ) を指定できます。
反変性: メソッドを継承する場合、親メソッドよりも限定性の低い引数の型 (スーパータイプ) を指定できます。
例:
class_name Parent
func get_property(param: Label) -> Node:
# ...
class_name Child extends Parent
# `Control` is a supertype of `Label`.
# `Node2D` is a subtype of `Node`.
func get_property(param: Control) -> Node2D:
# ...
Array
要素の型の指定
Array
の型を定義するには、型名を []
で囲みます。
An array's type applies to for
loop variables, as well as some operators like
[]
, []=
, and +
. Array methods (such as push_back
) and other operators
(such as ==
) are still untyped. Built-in types, native and custom classes,
and enums may be used as element types. Nested array types
(like Array[Array[int]]
) are not supported.
var scores: Array[int] = [10, 20, 30]
var vehicles: Array[Node] = [$Car, $Plane]
var items: Array[Item] = [Item.new()]
var array_of_arrays: Array[Array] = [[], []]
# var arrays: Array[Array[int]] -- disallowed
for score in scores:
# score has type `int`
# The following would be errors:
scores += vehicles
var s: String = scores[0]
scores[0] = "lots"
Godot 4.2以降 for
ループでループ変数の型を指定することもできます。たとえば次のように書くことができます:
var names = ["John", "Marta", "Samantha", "Jimmy"]
for name: String in names:
pass
配列は型なしですが、 for
ループ内の name
変数は常に String
型になります。
型キャスト
型キャストは型付き言語の重要な概念です。キャストは、ある型の値を別の型へ変換することです。
ゲーム内に extends Area2D
した敵がいると仮定してください。あなたはそれを PlayerController
と呼ばれるスクリプトが付いている CharacterBody2D
と衝突させたいのです。衝突を検出するには body_entered
シグナルを使用します。型付きコードの _on_body_entered
コールバックでは、検出したボディは一般的な PhysicsBody2D
になり、 PlayerController
にはなりません。
この PhysicsBody2D
がプレイヤーであるかどうかを確認するには、 as
キャストキーワードを使用し、再度コロン :
を使用して変数にこの型を使用させます。これにより変数は PlayerController
型に固定されます:
func _on_body_entered(body: PhysicsBody2D) -> void:
var player := body as PlayerController
if not player:
return
player.damage()
ここではカスタムされた型を扱っているため、 body
が PlayerController
を継承しない場合、 player
変数は null
に設定されます。これを使ってbodyがPlayerControllerかどうかをチェックできます。このキャストのおかげで、player変数のオートコンプリートもできるようになります。
注釈
as
キーワードは実行時に型が一致しない場合、エラーや警告を表示せず暗黙的に null
にキャストします。これは場合によっては便利ですが、バグが発生する可能性もあります。この動作が意図されている場合にのみ、 as
キーワードを使用してください。より安全な代替方法は is
キーワードを使用することです:
if not (body is PlayerController):
push_error("Bug: body is not PlayerController.")
var player: PlayerController = body
if not player:
return
player.damage()
You can also simplify the code by using the is not
operator:
if body is not PlayerController:
push_error("Bug: body is not PlayerController")
Alternatively, you can use the assert()
statement:
assert(body is PlayerController, "Bug: body is not PlayerController.")
var player: PlayerController = body
if not player:
return
player.damage()
注釈
組み込み型でキャストしようとして失敗すると、Godotはエラーをスローします。
セーフ・ライン
セーフ・ラインを確保するためにキャストを使用することもできます。セーフ・ラインはあいまいなコード行(ライン)が安全(セーフ)な型であることを教えてくれます。型指定されたコードと動的なコードを混在させると、Godotは実行時に命令がエラーを引き起こすかどうかを知るための十分な情報が得られない場合があります。
これは子ノードを取得したときに起こります。たとえばタイマーを考えてみましょう。動的コードでは、$Timer
でノードを取得できます。GDScriptは ダック・タイピング をサポートしているので、あなたのタイマーが Timer
型であっても、それは Node
であり Object
でもあり、その2つのクラスを継承しています。動的GDScriptでは、ノードが呼び出す必要のあるメソッドを持っている場合、その型については気にする必要はありません。
ノードを取得したときに期待される型をGodotに伝えるためにキャストを使用できます: ($Timer as Timer)
、 ($Player as CharacterBody2D)
など。Godotは、そのタイプが機能することを確認し、機能する場合は、行番号がスクリプトエディタの左側で緑に変わります。

セーフ・ラインではない行(line 7)とセーフ・ライン (line 6 とline 8)
注釈
セーフ・ラインは必ずしもコードが優れている、または信頼性が高いことを意味するわけではありません。 as
キーワードに関する上記の注意を参照してください。例えば:
@onready var node_1 := $Node1 as Type1 # Safe line.
@onready var node_2: Type2 = $Node2 # Unsafe line.
node_2
宣言はセーフでない行としてマークされていますが、 node_1
宣言よりも信頼性が高くなります。シーン内のノード型を変更し、誤ってスクリプト内で変更するのを忘れた場合でも、シーンがロードされるとすぐにエラーが検出されるためです。 node_1
でそれが発生すると、変数は暗黙的に null
にキャストされ、後でエラーが検出されます。
注釈
セーフ・ラインの色分けをオフにしたり、エディタ設定でカラーを変更することができます。
静的と動的: どちらかのみを利用する
型付きGDScriptと動的GDScriptは、同じプロジェクト内に共存できます。しかし、コードベースの一貫性のためにも、仲間のためにも、どちらかスタイルに統一することをお勧めします。同じガイドラインに従うことで全員が協力しやすくなり、他の人が書いたコードを素早く読んで理解できるようになります。
型付けされたコードはもう少し記述が必要ですが、上で説明したような利点があります。以下のコードは同じ空のスクリプトの動的スタイルの例です:
extends Node
func _ready():
pass
func _process(delta):
pass
そして静的型付けのコードでは:
extends Node
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
このように、エンジンの仮想メソッドで型を使用することもできます。シグナルのコールバックも、他のメソッドと同様に、型を使用できます。動的スタイルの body_entered
シグナルは次のとおりです:
func _on_area_2d_body_entered(body):
pass
そして、同じコールバックに型ヒントを付けます:
func _on_area_entered(area: CollisionObject2D) -> void:
pass
警告システム
注釈
GDScriptの警告システムに関する詳細なドキュメントは GDScript警告システム に移動しました。
Godot gives you warnings about your code as you write it. The engine identifies sections of your code that may lead to issues at runtime, but lets you decide whether or not you want to leave the code as it is.
特に型が指定されたGDScriptのユーザーを対象とした警告が多数あります。デフォルトではこれらの警告は無効になっていますが、プロジェクト設定で有効にすることができます (デバッグ > GDScript と 高度な設定 が有効になっていることを確認してください)。
常に静的型を使用したい場合は UNTYPED_DECLARATION
警告を有効にできます。さらに、より読みやすく信頼性が高く、より冗長な構文を希望する場合は、 INFERRED_DECLARATION
警告を有効にすることができます。
UNSAFE_*
警告は、アンセーフな行よりもアンセーフな操作をより顕著にします。現在 UNSAFE_*
警告は、アンセーフ・ラインがカバーするすべてのケースをカバーしているわけではありません。
一般的なアンセーフな操作とセーフな操作
UNSAFE_PROPERTY_ACCESS
と UNSAFE_METHOD_ACCESS
警告
この例では、プロパティを設定し class_name MyScript
でアタッチされたスクリプトを持ち、 extends Node2D
したオブジェクトのメソッドを呼び出すことを目的としています。オブジェクトへの参照を Node2D
として持っている場合 (たとえば、物理システムによって渡されたものなど)、最初にプロパティとメソッドが存在するかどうかを確認し、存在する場合はそれらを設定して呼び出すことができます:
if "some_property" in node_2d:
node_2d.some_property = 20 # Produces UNSAFE_PROPERTY_ACCESS warning.
if node_2d.has_method("some_function"):
node_2d.some_function() # Produces UNSAFE_METHOD_ACCESS warning.
ただし、プロパティとメソッドが参照される型 (この場合は Node2D
) に存在しないため、このコードは UNSAFE_PROPERTY_ACCESS
および UNSAFE_METHOD_ACCESS
の警告を生成します。これらの操作を安全にするには、最初に is
キーワードを使用してオブジェクトが MyScript
型であるかどうかを確認し、次にそのプロパティやプロパティを設定できる MyScript
型の変数を宣言してメソッドを呼び出します:
if node_2d is MyScript:
var my_script: MyScript = node_2d
my_script.some_property = 20
my_script.some_function()
あるいは変数を宣言し as
演算子を使用してオブジェクトのキャストを試みることもできます。次に変数が割り当てられていることを確認して、キャストが成功したかどうかを確認します。
var my_script := node_2d as MyScript
if my_script != null:
my_script.some_property = 20
my_script.some_function()
UNSAFE_CAST
警告
この例では、コリジョンエリアに入るオブジェクトに接続されたラベルにエリアの名前を表示したいと考えています。オブジェクトが衝突領域に入ると、物理システムは Node2D
オブジェクトを使ってシグナルを送信します。そして必要なことを行うための最も簡単な (ただし静的に型指定されない) 解決法は次のように実現できます。
func _on_body_entered(body: Node2D) -> void:
body.label.text = name # Produces UNSAFE_PROPERTY_ACCESS warning.
label
が Node2D
で定義されていないため、このコード部分は UNSAFE_PROPERTY_ACCESS
警告を生成します。これを解決するには、まず label
プロパティが存在するかどうかを確認し、次のように text プロパティを設定する前にそれを Label
型にキャストします。
func _on_body_entered(body: Node2D) -> void:
if "label" in body:
(body.label as Label).text = name # Produces UNSAFE_CAST warning.
ただし body.label
は Variant
型であるため、これにより UNSAFE_CAST
警告が生成されます。必要な型のプロパティを安全に取得するには、プロパティを Variant
値として返すか、存在しない場合は null
を返す Object.get()
メソッドを使用します。次に is
キーワードを使用して正しい型かどうかを判断し、最後に静的に型指定された変数を宣言します:
func _on_body_entered(body: Node2D) -> void:
var label_variant: Variant = body.get("label")
if label_variant is Label:
var label: Label = label_variant
label.text = name
型の指定ができないケース
この紹介の締めくくりに、型ヒントを使用できないケースを取り上げましょう。 以下の例はすべて 構文エラー が発生します。
配列または辞書内の個々の要素の型を指定することはできません:
var enemies: Array = [$Goblin: Enemy, $Zombie: Enemy] var character: Dictionary = { name: String = "Richard", money: int = 1000, inventory: Inventory = $Inventory, }
ネストされた型は現在サポートされていません:
var teams: Array[Array[Character]] = []
要約
型付きGDScriptは強力なツールです。より構造化されたコードの記述、一般的なエラーの回避、スケーラブルシステムで信頼性の高いシステムの作成に役立ちます。静的型によりGDScriptのパフォーマンスが向上し、将来的にはさらなる最適化が計画されています。