Hello! I have a problem with my project: a new instance of my ball scene isn’t detected by either of my goals (Area2D), even though it acts fine with everything else. I have configured all of the collision layers and masks properly, but there’s clearly something else wrong.
The way my game works is that whenever something enters either of the Area2Ds (I have a body_entered signal coming from both of them), it checks if the entered body is part of the global “Ball” group I made. If not, it gets added, an “increase points for appropriate player” fires depending on the goal scored and the object gets freed using queue_free() method. A snippet from my ball script below:
signal LeftGoalScored
signal RightGoalScored
func _on_left_goal_body_entered(body): #Signal coming from the left goal
var condition = body.is_in_group("Ball")
if not condition:
body.add_to_group("Ball")
LeftGoalScored.emit()
queue_free()
else:
LeftGoalScored.emit()
queue_free()
func _on_right_goal_body_entered(body): #Same thing, but for the right
var condition = body.is_in_group("Ball")
if not condition:
body.add_to_group("Ball")
RightGoalScored.emit()
queue_free()
else:
RightGoalScored.emit()
queue_free()
The execution continues on top of the scene tree, where I have a script attached to a Node2D. The script below:
The new ball isn’t detected by either of the goals. I checked using print-statements.
Also I think it’s worth mentioning here that I put the StaticBody2Ds (ceiling and floor) specifically to a different collision layer, because they were interfering with my goals (corners were touching). The collision layers go as follows:
This script is attached to my ball, which is a scene on it’s own. And about your question, i guess the check doesn’t do anything. I removed it now. I’ll try your suggestion about the body.queue_free() now.
Edit:
Thanks for the suggestion! I applied it, but nothing changes.
If this script is part of the Ball then you have to connect these signals when you make a new ball. I’d recommend moving this goal checking script to the goals instead for simplicity.
You could connect the signals like so, but again this can be avoided if the script is on the goals instead.
Do you mean that i should make a specific script for each of the goals or move the goal checking system to the top of my scene tree (the code that you are referencing in your last reply) ?
Either one will work better than the Ball, I suppose the top of the scene would be best since it already has functions for scoring a goal, you would only need to add body.queue_free() to the left/right_goal_scored connections.
I removed everything from the ball script like the signals, checks etc… However, i fear i might have broken something. Ball gets freed from the queue, but scores dont update nor the new ball doesnt spawn.
I kinda understand what your code does, but did i do something wrong? I’ll try to figure it out in the meantime.
I recommended either moving the script, or connecting signals, not both. You can remove my previous code sample.
Since the goal scored functions are on the same script you do not need the GoalScored signals, only connecting the area’s body_entered signal through the editor to the top script.
The difference in setup is that outside connections are not part of a scene, you had to connect the Ball to various nodes in the editor, but when the ball is destroyed so are those connections. When you add a new Ball it is exactly and only as it is defined in it’s .tscn scene file, no external connections.
So to circumvent removing and re-attaching connections you can only connect to the nodes you know will not be destroyed, the Goals and the root’s script. Signals do not know or care where you connect them so a Goal → Root connection is just as valid and functional as a Goal → Ball connection, but the latter is destroyed with the Ball. Maybe you think a collision base signal must be connected to the colliding objects, but that is not so, the connected function will have the other colliding body through the body argument.