Shooting with Signals?

WAAAAAAWAWAWAAAAAAWAWA Posts: 15Member
edited October 10 in Programming

Hi!
I have a basic 2d gun set up, so that whenever the player shoots and it's raycast is colliding the player emits a signal.
I also have a box set up, so that when the player emits the signal it gets damaged.
Problem is:
When any box gets damaged, every box in the scene would lose a life.
How do I make the code to target what it's hitting specifically?
Here's my code...

for the player:

func _input(event):
    if event.is_action_pressed("shoot") and gun_ray.is_colliding():
        emit_signal("shot_fired", gun_ray.get_collision_point()) 

for the box:

func _on_Player_shot_fired(arg):
    emit_signal("box_1_damaged")
    print(lives)

func _on_Box_box_1_damaged():
    lives -= 1

and just because, here's code that spawns a particle effect on the point of impact (found on the root node):

extends Node2D

var hit_effect = preload("res://Scenes/HitEffect.tscn")

func _generate_hit_effect(hit_position: Vector2):
    var effect = hit_effect.instance()
    add_child(effect)
    get_node("HitEffect").position = hit_position


func _on_Player_shot_fired(hit_position: Vector2):
    _generate_hit_effect(hit_position)

thanks so much in advance!


Tags :

Answers

  • TwistedTwiglegTwistedTwigleg Posts: 1,677Admin

    The reason every box is getting damaged is because the signal is sent to every connected object, so all of the boxes get the signal that the bullet collided with it. There are a few ways you could fix it. I listed a couple below, though I have not tested the code.


    Method one: Pass the hit object as a parameter in the signal:

    Player code:

    func _input(event):
        if event.is_action_pressed("shoot") and gun_ray.is_colliding():
            emit_signal("shot_fired", [gun_ray.get_collision_point(), gun_ray.get_collider()])
    

    Box code:

    func _on_Player_shot_fired(args):
        if (arg[1] == self):
            emit_signal("box_1_damaged")
            print (lives)
        else:
            pass # This box was not hit by the raycast
    func _on_Box_box_1_damaged():
        lives -= 1
    

    Method two: Call the function directly on the box that got hit instead of using signals

    Player code:

    func _input(event):
        if event.is_action_pressed("shoot") and gun_ray.is_colliding():
            var other_object = gun_ray.get_collider()
            if other_object.has_method("_on_Player_shot_fired"):
                other_object._on_Player_shot_fired()
    

    Box code:

    func _on_Player_shot_fired(arg):
        emit_signal("box_1_damaged")
        print (lives)
    func _on_Box_box_1_damaged():
        lives -= 1
    

    There are other ways to do it, but those are the two I'd try first. The main thing is you'll either need to pass a variable that can be used to identify which box was hit, or you'll need to call the function that damages the box directly on the box that was hit. The issue you are having is because all of the boxes are connected to the same signal, so they all act like they got hit when the signal is emitted.

    Hopefully this helps :smile:

  • WAAAAAAWAWAWAAAAAAWAWA Posts: 15Member

    Brilliant, just what I was looking for.
    Will play around with this later today.

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file