Registration files and attaching scripts
Godot Kotlin/JVM uses source files for classes declared in the current Godot project and registration files for classes contributed by external dependencies.
- Project classes are attached through their
.kt,.java, or.scalasource file. - Dependency classes have no source file inside the Godot project. The Gradle plugin generates a
.gdjregistration file for each usable registered dependency class so it can be attached in the editor.
Source files .kt, .java and .scala
Just like GDScript, you can directly attach Kotlin, Java, and Scala files from the current Godot project to Nodes as scripts. This is the default representation for project classes.
The limitations are the following:
- The source file must be inside both the Godot project and a configured Gradle source set.
- The source file name, without its extension, must match the simple name of the script class.
- Keep one attachable script class in each source file.
- The registered class information is available after a successful build. Before then, Godot keeps a best-effort source placeholder.
Use the source file directly for project classes.
Registration files .gdj
For each non-abstract registered class discovered in an external dependency, the build generates a corresponding .gdj registration file. Like source files, these files can be attached to Nodes.
They make dependency classes available when their source files are not part of the Godot project:
- Each dependency class gets its own
.gdj, including classes from different modules and libraries. - A dependency source file can contribute a separate
.gdjfor each registered class it contains. - Registration files are language agnostic: Kotlin, Java, and Scala dependencies use the same format.
By default, dependency registration files are generated into a folder called gdj in the root of your Godot project.
You can however configure the Godot root and the base directory used for newly created registration files inside your build.gradle.kts:
1 2 3 4 5 6 7 8 9 10 11 | |
During the sync step, the Gradle plugin scans the configured Godot project for existing dependency .gdj files. Matching files are updated in place, obsolete ones are deleted, and only newly discovered dependency registrations are copied into registrationFilesDirectory.
Reason
Contrary to GDScript, Kotlin is a compiled language. Hence, if you use a library which defines scripts you can not attach those to nodes anymore as the source files don't exist. You only have a jar of the library. While in GDScript you still have the sources when using an addon. With our registration files our compiler plugin is able to extract those from the libraries you use and provide them to you, so you can also attach scripts from libraries you use.
Class and member registration
Unlike GDScript or C#, JVM declarations pass through a registration step before Godot can use them. The default behavior follows registration annotations and their implied meaning, which keeps the Godot-facing boundary intentional without requiring every annotation to be repeated.
See the registration guide for the complete rules, or continue with the guides for classes, properties, and functions.
Instance types and singletons
Creating a new instance of a Godot type can be done like any JVM object.
1 2 | |
1 2 | |
1 2 | |
Godot's singletons are exposed as static access points.
1 | |
1 | |
1 | |
Core types
Godot's built-in types are passed by value (except for Dictionary and VariantArray - more on this later), so the following snippet won't work as expected.
1 2 | |
1 2 | |
1 2 | |
You are actually mutating a copy of the rotation property, not a reference to it. To get the desired behaviour you have to re-assign the copy back.
1 2 3 | |
1 2 3 | |
1 2 3 | |
This approach introduces a lot of boilerplate, so this binding provides a concise way of achieving the same behaviour. Only in Kotlin
1 2 3 | |
The snippet above is functionally equivalent to the previous one.
Collection types
While VariantArray and Dictionary are passed by reference, the value returned by the retrieval methods (VariantArray.get(...) and Dictionary.get(...)) are not.
1 2 | |
1 2 | |
1 2 | |
To get the desired behaviour, you can re-assign the copy back or in a similar fashion as before, this binding provides a better alternative.
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
Enums and constants
Godot enums are mapped to Kotlin enums, the generated enum exposes a value property that represents the value in Godot. Constants in Godot classes that represent an enum value (such as Node.PAUSE_MODE_INHERIT) are not present in this module, please use the generated enum instead (Node.PauseMode.INHERIT).
Renamed symbols
To avoid confusion and conflict with Kotlin types, the following Godot symbol is renamed.
Array->VariantArray(to avoid confusion with a built-in type in Kotlin)PackedXArray::toByteArray->PackedXArray::toPackedByteArray(to avoid confusion with a built-in type in Kotlin)PackedByteArray::toXArray->PackedByteArray::toPackedXArray(to avoid confusion with a built-in type in Kotlin)- All enum values are shortened, the name of the enum itself has been removed. Here are some examples:
Error.ERR_PARAMETER_RANGE_ERROR->Error.PARAMETER_RANGEMethodFlags.METHOD_FLAG_NORMAL->MethodFlags.NORMALProcessThreadMessages.FLAG_PROCESS_THREAD_MESSAGES_PHYSICS->Error.FLAG_PHYSICS
Global functions
In GDScript, some functions are always available (such as mathematical or RNG functions). The complete list can be found on the following page of Godot's documentation.
In Kotlin, Java, and Scala, global functions are available through the GD singleton helpers. However, don't forget that some functions couldn't be reproduced exactly on the JVM side.
For example, load() is available but preload() is not.
Additional functions
For comfort, some objects got some additional functions to enjoy some Kotlin syntax sugar. You can find them all in this folder.
Notifications
Register notification handlers with @Notification.
Unlike GDScript and C++, you do not override _notification directly. Instead, each handled notification is a regular zero-argument method annotated with the notification number it handles.
If several methods in the class hierarchy handle the same notification, they are all called. Normal notification delivery follows Godot's inheritance order, from parent to child. Reversed notification delivery calls them from child to parent.
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
Notification handlers are not registered as callable Godot methods. In explicit and inferred registration modes,
@Notification is enough to select the method. In automatic mode, a method only becomes a notification handler when
the annotation is present.
StringName and NodePath
Several Godot functions take StringName or NodePath as a parameter.
It's often more convenient to directly use a String and convert it.
This kind of operation can be costly so we provide extension functions which cache the result of the conversion for later calls:
1 2 3 | |
1 2 3 | |
1 2 3 | |
You can also use the non-cached version of them if you simply want ease of conversion:
1 2 | |
1 2 | |
1 2 | |
Logging
If you want logs to appear both in CLI and in the Godot Editor you will have to use the print functions inside the GD singleton like:
1 | |
1 | |
1 | |
Kotlin's print functions, on the other hand, will only print to CLI! They won't print to Godot editor's output panel.