Godot Version
4.4.1
Question
I’m quite new on my Godot journey and a little confused as to the best approach to use for the following…
In my game my ‘enemies’ will be a mixture of PhysicBodies2D (Static, Rigid and Character). I’d like to create some kind of ‘base_enemy’ scene / script for all the come properties (health, loot_drop, contact_damage…) and functions (take_damage, line_of_sight_to_player…)
If my enemies were all, for example, RigidBody2D’s I would create a base scene with that as a root and then use ‘New inherited scene’. But I don’t think that will work in my case as I’ve got different root node types?
At the moment I’ve got a autoload script for the common functions, but that feels pretty clunky.
Just wondering what options I’ve got for approaching this?
Is the main reason you want to do this so you can re-use code? If so, here’s an alternative to using inheritance.
Consider making lots of tiny component nodes that all serve one particular function. For example, a HealthComponent
that tracks the player’s health, and a DropLootComponent
that governs if an enemy drops something if defeated, and if so, what. If you have a number of these components then you can mix and match when making a new enemy by including certain components but not others.
Example scripts (incomplete, they just serve as inspiration):
#HealthComponent
class_name HealthComponent extends Node
signal defeated
@export var health : int = 10
func take_damage(amount : int)->void:
health -= amount
if health <= 0:
defeated.emit()
#DropLootComponent
class_name DropLootComponent extends Node
@export var item : SomeEnumClass.ITEM_LIST = SomeEnumClass.ITEM_LIST.CRAB_LEGS
@export var drop_chance : int = 10
func drop()->void:
if randi # Drop logic goes here
By adding these scenes to any enemy scene, you can now tie them together via the top level script:
# Some enemy class
@export var health_component : HealthComponent = null #Set via inspector
@export var drop_loot_component : DropLootComponent = null # Same
func _ready()->void:
if health_component != null:
health_component.defeated.connect(_on_defeated.bind())
func _on_defeated()->void:
if drop_loot_component != null:
drop_loot_component.drop()
1 Like
Wow, didn’t know you could do this. So you’re storing a class / script in a variable and then you can access anything in that script directly. Pretty neat.
1 Like
Broadly speaking, yes. But you can only add nodes that are present in the current scene.