Body_entered only work when I play current scene, not instantiate it

Godot Version

Godot v4.1.1

Question

I am making a bullet hell system, similiar to that of Undertale. My battle template and test battle is a scene, template.tcsn. When I play template.tcsn via “play current scene”, the bullet hell system works fine. When I play the game normally and instantiate it under a CanvasLayer, however, the body_entered signal connects, but does not work.

Here is bullet.gd:

extends Area2D

func _ready():
	print("Start")

func _on_body_entered(body):
	print("Enter")
	if body.name == "Soul":
		print("damage")
		Global.battle._damage()

(body_entered is connected via editor. I have tried connecting it via code as well, no difference is made.)

When I play template.tcsn via current scene, it prints “start, enter, damage”. When I play via normal means, it only prints “start”.

Can you show some of your scene setups? Is there any chance “Soul” is instantiated twice? filtering by name is usually fragile in Godot since siblings must have unique names they are garbled if matching.

The thing is, it doesn’t print “Enter” either, meaning it doesn’t collide at all. Also, it’s the whole battle scene being instantiated under the CanvasLayer, not the soul.

Or the callback simply isn’t connected correctly.

Either way, you probably want to provide us with more info, ideally the whole project. There’s nothing wrong with the code you posted, so the cause of your problem must lie elsewhere!

Notice by going to res://scenes/battle/template.tcsn and playing it via the “play Current Scene” button, it works fine. (You have to attack first to get the bullet hell attack.)
To test how to instantiate it, play, start a new game, leave the house room, and interact with the “test enemy” character. The bullet hell system doesn’t work there.
Also, I’m pretty new to Godot, don’t mind my hack-job code :slight_smile:

I believe it’s due to the game being paused. If you set your template to pause on ready, and “Always” process the same effect happens. I wish I found a way for collisions to keep registering but I think your best bet and best practice would be to avoid pausing during gameplay.

When the battle pops up, I need the other scene to be paused.

You can pause a certain scene without pausing the entire SceneTree with process_mode variable (set to ProcessMode.PROCESS_MODE_DISABLED)