2022-04-13
Godot experiments
3:15pm
Playing around with ways to avoid the “editable children” pitfall in godot. Stay tuned.
6:30pm
Node tree for our custom node called “Thing”:
Thing
├── Area2D
│ └── CollisionShape2D
└── Sprite
“Thing.gd”:
tool
extends Node2D
export var sprite: Texture = null setget set_sprite
export var collision_shape: Shape2D = null setget set_collision_shape
onready var _sprite: Sprite = $Sprite
onready var _collision_shape: CollisionShape2D = $Area2D/CollisionShape2D
func _get_configuration_warning() -> String:
var warnings = []
if sprite == null:
warnings.append("missing sprite")
if collision_shape == null:
warnings.append("missing collision_shape")
return PoolStringArray(warnings).join("; ")
func set_sprite(value: Texture) -> void:
sprite = value
if not is_inside_tree():
yield(self, "ready")
if _sprite != null:
_sprite.texture = sprite
func set_collision_shape(value: Shape2D) -> void:
collision_shape = value
if not is_inside_tree():
yield(self, "ready")
if _collision_shape != null:
_collision_shape.shape = collision_shape
The idea here is to encapsulate all of the “wiring” by exposing the
public attributes as exported variables. In this case, two elements: the
sprite texture (Sprite), as well as a collision box
(Area2D, which requires some kind of
CollisionShape-esque child).
A brief tour:
tool
This is necessary for running the script in the editor (which allows for live updates).
Godot docs: running code in the editor
export var ...
This allows for assigning instance variables via the editor UI.
func _get_configuration_warning(): -> String:
This allows for displaying a warning (in the editor and the console), basically I’m using it here to define required attrs.
Godot docs: _get_configuration_warning
The setter functions for the sprite and
collision_shape attributes allows us to wire the custom
nodes attributes into the private children, as necessary. One little
“gotcha” here, the yield business is for handing the case
when the setter is called during initial construction of the node,
otherwise the wiring never actually happens. The yield lets
us pause execution until the ready signal has fired,
letting us know the base node has entered the editor tree.
I’ve got a few places I want to get some real-world practice with this particular pattern, so stay tuned for more info.