Hey guys, I was working on a 2D game that deals with animation instances. I have only been on Godot for 3 days so forgive me if my code is messy or my question not following some sort of precedent. My problem is that when I create a new instance which contains an AnimationPlayer as a child, the AnimationPlayer simply does not work for the instance, but does for the original copy. I've tried scouring the internet for hours, but nothing has come of it. I'll link some example code.

extends Area2D
func _ready():
->set_visible(true)
->set_collision_layer_value(1, true)
func _on_body_entered(_body):
->print("Fired")
->$ChildAnimator.play("Animation")
->await get_tree().create_timer(1.0).timeout
->set_visible(false)
->set_collision_layer_value(1, false)
->print("Registered")
->queue_free()

And the tree looks like this

\/ Area2D(Script)
|--AreaCollider(CollisionShape2D)(NoScript)
|--Texture(Sprite2D)(NoScript)
|__ChildAnimator(AnimationPlayer)(NoScript)

As far as the code goes, whenever I go into testing and a physics body collides with the Area2D, both of the print statements are activated, but i can tell by the frequency that the await get_tree().create_timer(1.0).timeout and queue_free() lines are also nonfunctioning, which makes me think the problem has to do with the tree somehow, even though the Texture(Sprite2D) is working fine. For the record, I've tried moving the script to the AnimationPlayer, Setting the specific animation to unique using the animation manager, I've restarted Godot multiple times. I am really at a loss for what to do, any help would be greatly appreciated.

  • Primitiveman495 move set_collision_layer_value before everything else, to prevent the signal from being called multiple times.
    I'm thinking that the signal could be triggering multiple times, creating multiple timers AND preventing queue_free(), and restarting the animation. But that would result in a bugged animation.

    What happens in the game?
    1 - Does the animation only work in ONE instance but not the others?
    2 - Does the animation not work at all?
    3 - Does "Fired" appear only once?
    4 - Does "Fired" appear multiple times?
    5 - Do the instances disappear?
    6 - During game, go to the editor and click on "remote", it will show you the scene_tree of the game being run.

If you need to see any other code or need any form of context I'll be happy to give you it

The only thing I notice is that $ChildAnimator has a different name from "Animator", but that should throw an error.
Are there any errors in the console?

The function should also be connected but you say it works with a single instance.

Try commenting the await and see if the node selfdestructs. If it does it must be a problem with the timer.
The animation could be not triggering because it's set in a different part of the code, maybe in process.

    Jesusemora oh sorry about that, that was a mistake in typing, in reality ChildAnimator and Animator have the same name, I'll go fix that in editing. Also no, there are no errors in the console.

    I just tried to comment await, but it didn't change anything, if you have any more suggestions I'll be happy to hear them.

      Primitiveman495 Is your object saved as a scene and instantiated on the main scene or did you just duplicate it? it has to be saved as a scene and instantiated to work.
      On the tree there are two buttons, a + and a "chain" icon. one creates a new node, the other instantiates a scene.

      Yes, i do have it saved as an independent scene, I also have two screenshots, one of the main scene's tree and one of the Area2D's scene (Goal).

      I also recently changed the Animator to be the texture's child, incase that would fix anything (it did not).

        Primitiveman495 ok, so:
        the function is connected
        print("fired") writes a message

        but animation player doesn't play, that is not what's strange, because it could be a million things ( and it was fine as children of Area2D, don't change that)

        the fact that the node doesn't selfdestruct with queue_free() is what's weird.

        My theory: It could be something to do with signals or collisions preventing the node from being terminated. Could be that the node is sending a signal to itself and that's why it doesn't work?

        Try moving the script to a Node2D so that it looks like this:

        Node2D (script)
             |
             Goal(Area2D)
                  |
                  Collider
             Sprite
             AnimationPlayer

        disconnect the signal, then change the structure, then
        connect the Area2D again but with the script in Node2D
        you can create a Node2D anywhere and right_click to turn it into the scene root

        the script would then detect a collision in Area2D but destroy the parent node Node2D.

        IF the problem is with queue_free(). It could also be a problem with the animationplayers preventing the node from selfdestructing because they are somehow altering a sprite in a different scene??? I'm not very familiar with 2D.
        But try using an AnimatedSprite2D instead of a sprite2D with AnimationPlayer, it lets you create different animations and play them, all in the same node. Maybe that will fix it.
        Or not? AnimatedSprite2D lets your create animations with sprites, AnimationPlayer allows you to change other properties like scale and rotation. So if you are only using spritesheets use an animatedsprite2D, otherwise... the sprite2D with animationplayer should work.

        Is there MORE code in your scripts that is doing something else?

        So the node was connected to itself, and I did as you advised and added the Node2D and the script to it, so now the tree looks like this:

        It's still not working however, the console is repeating "Fired" and "Registered" as it was before.

        The only problem with an animatedsprite2d is that the animation i'm using decreases the opacity, meaning that to achieve the same effect with an animatedsprite2d means i would have to go frame by frame and decrease the opacity manually, so that is a last resort for me.

          Primitiveman495 move set_collision_layer_value before everything else, to prevent the signal from being called multiple times.
          I'm thinking that the signal could be triggering multiple times, creating multiple timers AND preventing queue_free(), and restarting the animation. But that would result in a bugged animation.

          What happens in the game?
          1 - Does the animation only work in ONE instance but not the others?
          2 - Does the animation not work at all?
          3 - Does "Fired" appear only once?
          4 - Does "Fired" appear multiple times?
          5 - Do the instances disappear?
          6 - During game, go to the editor and click on "remote", it will show you the scene_tree of the game being run.

          so I moved the set_collision_layer_value before the await, but it didn't do anything. I'll list the results over here:

          1. The Animation only works with the original copy if i have it turned visible
          2. Both "Fired" and "Registered" spam in the console, I'll provide a picture
          3. the instances do not dissappear
          4. I tried the remote thingy and I discovered something a bit zany, I have the goal instance as I thought, but then i Have nodes named @Node2D That has a number ranging from one to infinity.



          Now i'm really confused

            Primitiveman495 Ok, that's good.

            Primitiveman495 I moved the set_collision_layer_value before the await, but it didn't do anything.

            that means there's nothing wrong with the code, we have exhausted all possibilities. It must be something with the nodes and scenes.

            Primitiveman495 The Animation only works with the original copy if i have it turned visible

            that is weird.

            mmmh... that appears to be working correctly.

            Primitiveman495 the instances do not dissappear

            also weird.

            Primitiveman495 I tried the remote thingy and I discovered something a bit zany, I have the goal instance as I thought, but then i Have nodes named @Node2D That has a number ranging from one to infinity.

            those are the copies of the goal instance. Remote allows you to see the objects in your game, you can select one at random and see it's nodes and the properties. You can use this to debug your game.

            I made a Scene to test AnimationPlayer and queue_free(), it's not exactly the same, but when I press "up", the correct instance plays a modulate opacity animation and then selfdestructs.

            Next thing to test is the other Nodes. maybe they are interacting with the properties of Goal or holding a reference.
            1 - How is goal spawned?
            2 - Is any other node interacting with it?
            3 - Are there other nodes that would collide with Goal and trigger code?
            4 - Try creating a new scene with an animationplayer, spawn a few instances of it and have them play animations. This is to test if the problem is with the AnimationPlayer.

            A good tip when fixing bugs: modify things one at a time, test things one at a time, remember what you changed, then put things the way they were before.
            Start from any point in your code and then go forwards or backwards until you find out where the problem is.
            Then reduce your code from something very complex to a few lines and test each line separately.
            This can be applied to any problem, it's how doctors diagnose patients and it's how we solve bugs.

            So I thought about something while I was away from my computer, with all those nodes being spawned, it could be a massive amount of goals being spawned in the one place, as I set the instance to a specific 2D vector. It would explain why fired and registered were being called so much, because there was so many in the same spot. It would also explain why the animation isn't working, because the new instances are being put on top of the activated ones. I'm gonna try to see if I have the instantiate function looping.

            That seemed to work, it turns out I had an looping "if" function that caused a bunch of instances to be spawned. Thank you for all your help on this, I appreciate it a lot man.