Why Inherited Scenes has the same behavior when it is instantiate more than once?

Godot Version

4.4

Question

I’ve been created a Parent Scene as EnemyBase and after that I created Inherited Scene from that as Child that is Enemy. Now, I am creating instances of child on the Level Scene but all child has the same behavior. When I do hit in one enemy the others enemies has receiving hit too. I don’t know why it is happens and how could I fix it.

Parent

class_name EnemiesBase extends CharacterBody2D

#DICT
var ANIMATIONS_ENEMY:Dictionary = { "idle" : "idle", 
                                    "walk" : "walk", 
                                    "attack" : "attack", 
                                    "hit" : "hit",
                                    "dead" : "dead" 
                                    }

#VAR
var _can_attack = false
var _collision_weapon_default_positionX:float
var _raycast_default_rotate_position:float
var _player_ref:Player
var _enemy_direction:Vector2 = Vector2.ZERO 
var _enemy_is_dead:bool = false
var _show_blood:bool = false
var _is_visible_on_screen:bool = false

#ONREADY
@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var ray_cast_2d: RayCast2D = $RayCast2D
@onready var collision_shape_2d_attack: CollisionShape2D = $AreaAttackBase/CollisionShape2D
@onready var timer_attack: Timer = $TimerAttack
@onready var collision_shape_2d: CollisionShape2D = $CollisionShape2D
@onready var timer_to_free: Timer = $TimerToFree
@onready var sound: AudioStreamPlayer2D = $Sound

#EXPORT
@export_category("EnemiesBase Cfg")
@export var speed:float = 50
@export var life_health:int = 20
@export var damage_attack:int = 5
@export var enemy_name:String = "Unnamed"



func _ready() -> void:
    _show_blood = GameSetup.show_blood()
    SignalManager.on_enemy_hit.connect(on_enemy_hit)
    _collision_weapon_default_positionX = collision_shape_2d_attack.position.x
    _player_ref = get_tree().get_first_node_in_group(GameManager.PLAYER_GROUP)  
    _raycast_default_rotate_position = ray_cast_2d.rotation
    set_default_scale_enemy()
    
    
func _physics_process(_delta: float) -> void:
    if(_enemy_is_dead):
        set_physics_process(false)
        return
    _flip_me()
    _enemy_move()
    
    
func _enemy_move() -> void: 
    if(_player_ref.is_player_upraycast_colliding() or _player_ref.is_player_downraycast_colliding()):
        animated_sprite.play(ANIMATIONS_ENEMY.idle)
        set_default_scale_enemy()
        return
    if((_player_ref != null) and 
       (_can_attack == false) and 
       (!ray_cast_2d.is_colliding()) and 
       (_is_visible_on_screen)):            
            var _player_collision:Vector2 = _player_ref.get_target_to_attack_position()
            var x_direction: float = sign(_player_collision.x - global_position.x)
            var y_direction: float = sign(_player_collision.y - global_position.y)
            _enemy_direction = Vector2(x_direction, y_direction)
            velocity = _enemy_direction * speed 
            animated_sprite.play(ANIMATIONS_ENEMY.walk) 
            set_default_scale_enemy()
            move_and_slide()    
        
func _flip_me() -> void:    
    if(_player_ref.global_position.x > global_position.x):
        animated_sprite.flip_h = false
        collision_shape_2d_attack.position.x = _collision_weapon_default_positionX
        ray_cast_2d.rotation = _raycast_default_rotate_position
    elif(_player_ref.global_position.x < global_position.x):
        animated_sprite.flip_h = true
        collision_shape_2d_attack.position.x = -_collision_weapon_default_positionX
        ray_cast_2d.rotation = -_raycast_default_rotate_position
        
func is_enemy_dead(damage:int) -> bool:
    life_health -= damage
    if(life_health <= 0):
        timer_to_free.start()
        call_deferred("disable_collisions") 
        return true
    return false
    
func disable_collisions() -> void:
    collision_shape_2d.disabled = true
    collision_shape_2d_attack.disabled = true
    ray_cast_2d.enabled = false
    
func kill_enemy() -> void:
    queue_free()
    
func on_enemy_hit(damage:int) -> void:
    print("Parent Enemy REceive Damage: ", damage)
    
func set_default_scale_enemy() -> void:
    EnemiesCfg.set_default_scale_animatedsprite2d(animated_sprite)

func _on_timer_to_free_timeout() -> void:
    kill_enemy()


func _on_visible_on_screen_notifier_2d_screen_entered() -> void:
    print("enemy is on scene")
    _is_visible_on_screen = true
    SignalManager.get_enemies_on_screen.emit(self)


func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
    print("enemy out of scene")
    _is_visible_on_screen = false

Child

class_name Caius extends EnemiesBase

@onready var blood: Node2D = $Blood

func _physics_process(delta: float) -> void:
    if(_enemy_is_dead):
        animated_sprite.play(ANIMATIONS_ENEMY.dead)
        return
    super._physics_process(delta)
    enemy_attack()

func enemy_attack() -> void:
    if(ray_cast_2d.is_colliding() and _can_attack == false and !_enemy_is_dead):        
        _can_attack = true
        animated_sprite.play(ANIMATIONS_ENEMY.attack)
        timer_attack.start()
        _player_ref.on_player_receive_hit(damage_attack)
        
func set_idle_animation() -> void:
    if(_enemy_is_dead):
        return
    animated_sprite.play(ANIMATIONS_ENEMY.idle)

func _on_timer_attack_timeout() -> void:
    _can_attack = false
    
#enemy hit dead
func on_enemy_hit(damage:int) -> void:  
    if(_player_ref.get_key_state_selected() != "ARMS"):
        display_blood()
    if(!is_enemy_dead(damage)):
        animated_sprite.play(ANIMATIONS_ENEMY.hit)
        if(animated_sprite.flip_h == true):
            global_position.x += global_position.x * 0.1
        elif(animated_sprite.flip_h == false):
            global_position.x -= global_position.x * 0.1
        animated_sprite.play(ANIMATIONS_ENEMY.dead)
        if(_player_ref.get_key_state_selected() == "ARMS"):
            SoundManager.execute_sound_punch(sound)
    if(is_enemy_dead(damage)):
        _enemy_is_dead = true
        animated_sprite.play(ANIMATIONS_ENEMY.dead)
        SoundManager.execute_sound_argh(sound)
        super.set_physics_process(false)
        
func display_blood() -> void:
    if(_show_blood):            
        for b in blood.get_children():
            SignalManager.on_execute_blood.emit(b)
                    
func _on_animated_sprite_2d_animation_finished() -> void:
    if(_can_attack):
        animated_sprite.play(ANIMATIONS_ENEMY.idle)

Your problem probably lies in when you fire this signal from SignalManager. All instances of your class, including children, listen to this signal. So when it fires, everything responds to it.

Can you post the code where you fire the signal from?

1 Like

Solved! I did using your suggestion. Thanks a lot