Yes, I completely agree with your point. My main concern right now is how to implement this binding layer elegantly.
For example, in my current game, I have trees, stones, animals, and mechanisms. Each entity is composed of a set of relatively independent functional nodes, with the root node responsible for binding these functional nodes together. Since this binding functionality is very generic - just managing, registering, and finding these components - it should only need one set of code inheriting from Node.
However, since these objects have different base classes (trees are StaticBody3D, animals are CharacterBody3D, mechanisms are RigidBody3D), it’s difficult to reuse this binding code across these objects, and we might need to copy-paste it many times (which is neither safe nor elegant).
But I’m very happy that after extensive research, I discovered that by using the node’s meta data, we can bypass this binding layer entirely, which feels great. Here’s a simple example:
Component usage example
Property component
class_name PropertyComponent:
extends Node
@export var health:int=0
func _ready():
get_parent().set_meta(“PropertyComponent”,self)
func hurt(amount: float) → void:
health -= amount
if health<0:
die()
func die():
passDamage component
class_name DamageableComponent:
extends Area3D
var property_com:PropertyComponent
func _ready():
get_parent().set_meta(“DamageableComponent”,self)
func get_property_com():
return get_parent().get_meta(“PropertyComponent”,null)
func take_damage(amount):
var propertycom=get_property_com()
if not propertycom:
printerr(“warning:no property com”)
return
propertycom.hurt(amount)No need to write binding code in objects anymore, avoiding the issues of GDScript not supporting multiple inheritance and different base classes
If components have interdependencies, they can be exposed via export and connected in the editor
class_name PlantTree:
extends StaticBody3DComponents can be directly added as child nodes in the scene tree, plug and play
Can also have PlantTree-specific code
class_name Animal:
extends CharacterBody3DPropertyComponent
DamageableComponent
Components can be directly added as child nodes in the scene tree, plug and play
Can also have Animal-specific code
Component usage example:
For bullet hits, we can filter bodies by component type and find the damageable component
Each function call is type-safe and supports editor hints
func _on_body_entered(body:ComponentManager):
var damageable_com:DamageableComponent=body.get_meta(“DamageableComponent”,null)
if damageable_com:
damageable_com.take_damage(10)