I'm trying to design a character system for my game. Considering I'll need a player and non-player characters - and non-player characters will further come in many more forms, making use of inheritance sounds almost necessary.
Right now, I'm trying to make every instance hold a dictionary of context options and I need the dictionary to be modified with every level of inheritance. From the documentation I learned that the constructor implicitly calls the parent constructor, and so does the _ready()
function as noted here.
... but first I wanted to test it, so I set up following scenes (slightly simplified):
New scene: Character
- Character (
Type: Character
- here I'm not sure why, should be justKinematicBody
)
... with the attached script:
extends KinematicBody
class_name Character
func _init():
print_debug(self.to_string(), " Character _init()")
func _ready():
print_debug(self.to_string(), " Character _ready()")
New inherited scene: Player
- Player (
Inherits: Character.tscn, Type: KinematicBody
)
... and detatched the Character.gd
script and attached a new script:
extends Character
class_name Player
func _init():
print_debug(self.to_string(), " Player _init()")
func _ready():
print_debug(self.to_string(), " Player _ready()")
... and I instantiate one Player scene as a child scene in my main scene (through editor, not code).
For some reason, whenever I instantiate Player, Godot consistently prints this:
[KinematicBody:1422] Character _init()
At: res://scenes/characters/Character.gd:22:_init()
[KinematicBody:1422] Character _init()
At: res://scenes/characters/Character.gd:22:_init()
[KinematicBody:1422] Player _init()
At: res://scenes/characters/player/Player.gd:26:_init()
[KinematicBody:1422] Character _ready()
At: res://scenes/characters/Character.gd:30:_ready()
[KinematicBody:1422] Player _ready()
At: res://scenes/characters/player/Player.gd:34:_ready()
However, when I instantiate only Character in its place, the output is as I'd expect:
[KinematicBody:1425] Character _init()
At: res://scenes/characters/Character.gd:22:_init()
[KinematicBody:1425] Character _ready()
At: res://scenes/characters/Character.gd:30:_ready()
Where is the extra _init()
call coming from? Sounds like something that could make a lot of mess if I didn't notice this and blindly used it.
Also why does Player show as a Type: KinematicBody
when hovering over it in the scene inspector and not like Type: Player
, the same way Character shows as Type: Character
- or why don't they both show up as Type: KinematicBody
?
Edit
Following @Vaillancourt's suggestion, I placed breakpoints at each of the print_debug()
calls. Stepping through the code, the last 4 prints behave as expected - first there's the Character constructor, implicitly called from the Player constructor, then the body of the Player constructor itself. This is clear from the backtrace. Same for the _ready()
calls. But before this, there's always one extra Character constructor call not called from the Player constructor.
Same goes when I put multiple Player instances into the scene. Both had the correct constructor calls preceded by one extra, separate call.
Putting a Character instance along with a Player instance to the scene resulted in a - once again - malfunctioning Player (three _init()
and two _ready()
calls) and a correctly functioning Character (just one _init()
and one _ready()
call).