-
-
Notifications
You must be signed in to change notification settings - Fork 33
GodotJSScripts
A javascript class can extend a Godot Object class:
This example is written in TypeScript.
import { Node, Signal0, Callable } from "godot";
import { signal } from "godot.annotations";
function seconds(secs: number) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(undefined);
}, secs * 1000);
});
}
export default class MyJSNode extends Node {
@signal()
test!: Signal0; // it's technically identical to Signal, but with type restriction for parameters
private _on_test() {
}
_ready() {
console.log("MyJSNode _ready");
this.test.connect(Callable.create(this, this._on_test), 0);
this.test.emit();
this.test.disconnect(Callable.create(this, this._on_test));
}
// it's also possible to use async functions in scripts (even the `_ready` call)
async call_me() {
let ticks = 5;
for (let i = ticks; i > 0; i--) {
(<Label>this.get_node("Control/Label")).text = `wait for ${i} seconds with await`;
await seconds(1);
}
(<Label>this.get_node("Control/Label")).text = `${ticks} seconds passed`;
}
}Warning
Explicitly defined constructor in script classes inherited from Godot Object are not recommended, because GodotJS constructs the script classes for special uses (such as CDO and cross-binding).
If it can't be avoided, always define it with an explicit argument identifier? any, and don't forget to call super(identifier).
For instance:
export default class MyExampleNode extends Node {
constructor(identifier?: any) {
super(identifier);
// do other things you want
//...
}
}You can instantiate a script class directly with new in scripts:
// do not pass any arguments to the constructor
let node = new MyExampleNode();Note
A class must be exported as default, otherwise the script will not recognized as a valid script class.
Compile the typescript source into javascript, and attach the compiled script to a Node:

Currently, GodotJS doesn't provide sufficient support for using code from npm packages. Because many factors are involved in it, such as:
- Scripts depend on functionalities of node.js which is not supported
- How the typescript/javascript project is packaged (archive into a single script file or not)
- Javascript modular standard variants may be involved
If a npm package just works, there is no guarantee that it does also work after packaging, GodotJS tries to export all dependant javascript sources into the targeting package.
Note
See read_xlsx.ts about using a npm package.
In GodotJS, class member properties/variables can be exported. This means their value gets saved along with the resource (such as the scene) they're attached to. They will also be available for editing in the property editor. Exporting is done by using the @export_ annotation.
export default class Shooter extends Sprite2D {
// type must be explicitly provided as the first parameter of @export_
// cuz static type is actually a phantom in typescript
@export_(Variant.Type.TYPE_FLOAT)
speed: number = 0;
// ...
}In this example the value 0 will be saved and visible in the property editor.
The retrieval of default value is implemented through Class Default Object (CDO). GodotJS will instantiate a pure javascript instance of the script class (Shooter in this example) as CDO, then the property value is read from CDO as default value in the property editor.
Note
Be cautious when coding within constructor, as it is probably called for initializing CDO.
@export_(Variant.Type.TYPE_STRING)
address: string = "somewhere"; // `:string` can be omitted here
@export_(Variant.Type.TYPE_INT)
age: number = 0; // `:number` can be omitted hereIf there's no default value, default value of the give type will be used (0 in this case).
@export_(Variant.Type.TYPE_INT)
age: number;Enum value properties can be exported with the built-in support in the property editor.
Note
So far, only int is supported as enum value.
@export_enum(MyColor)
color: MyColor = MyColor.White;The value can be easily chosen from a dropdown list in the editor.

NOT IMPLEMENTED FOR NOW
An icon can be used as node icon in the editor scene hierarchy with the annotation @icon.
@icon("res://icon/affiliate.svg")
export default class MySprite extends Sprite2D {
}![]()
Cyclic imports are allowed in GodotJS with some limits.
// file: cyclic_import_1.ts
import { CyclicClass2 } from "./cyclic_import_2";
// NOT OK: The behaviour is undefined if anything from cyclic imported modules is referenced in the script compile-run scope
// let a_name = CyclicClass2.something;
// NOT OK: extends a class from cyclic imported modules
// class BehaviorUndefined extends CyclicClass2 {}
// OK: references at runtime
export class CyclicClass1 {
static call1() {
console.log("call1");
CyclicClass2.call2();
}
static call3() {
console.log("call3");
}
}// file: cyclic_import_2.ts
import { CyclicClass1 } from "./cyclic_import_1";
export class CyclicClass2 {
static call2() {
console.log("call2");
CyclicClass1.call3();
}
}WRITE SOMETHING HERE
It's recommended to use external editor to write typescripts. Change the settings in Editor > Edtior Settings > Text Editor > Use External Editor, and replace the Exec Path with the code editor installed locally:

-
Scripting
-
Utilities
-
Experimental Features
-
Advanced
-
Misc