How do I call an AnimationPlayer from a different scene?

Godot Version

4.4.1 stable

Question

Hi, how can I play an animation that’s on a different scene?

I have an animation that shows an enemy taking damage. I want to play that animation once I hit the enemy. So the script that reduces the enemy’s health is on the Bullet script, that works without a problem, the enemy takes damage and then is ‘queued free’. The animation of the enemy taking damage is on a different scene. What would be the best way to access the animation and play it when the enemy gets hit?

This is the Bullet script where I attempt to call and play the enemy hurt animation in the _ready() function:

class_name Bullet extends Area2D

@export var speed := 750
@export var damage:= 1


var max_range := 1000.0
var _traveled_distance = 0.0

func _ready() -> void:
	body_entered.connect(func (body: Node) -> void:
		if body is Sword:
			body.health -= damage 
			var animation_player: AnimationPlayer = get_node("HurtSwordAnimation")
			animation_player.play("hurt_sword")
			_destroy()
	)
	
func _physics_process(delta: float) -> void:
	var distance := speed * delta
	var motion := Vector2.RIGHT.rotated(rotation) * distance

	position += motion
	
	_traveled_distance += distance
	if _traveled_distance > max_range:
		_destroy()
		
		
func _destroy():
	queue_free()

I’m getting an error that states: Cannot call method ‘play’ on a null value.

It is probably better to make a take_damage function on the body that handles the hurt animation.

To use get_node you must specify which node you are starting from, otherwise it assumes self. Try body.get_node instead.

Hey, thanks for your reply. I made the suggested changes but I’m still getting the same error:

Cannot call method ‘play’ on a null value.

I’m a bit confused by this since I have a reference to the animation player in the bullet script

@onready var hurt_sword_animation: HurtSword = $HurtSwordAnimation

here’s the ready function:


func _ready() -> void:
	body_entered.connect(func (body: Node) -> void:
		body.get_node("/root/SwordFollow/HurtSwordAnimation")
		if body is Sword:
			body.health -= damage 
			hurt_sword_animation.play("hurt_sword")
			_destroy()
	)

I’m also experimenting with your suggestion of adding a take_damage function on the body that handles the hurt animation. If I do that, how can I call that function from a different script?

Not sure why you would be using a /root/ path now, Did you set “SwordFollow” as a global? If so, use the global name, otherwise do not use a root path.

To call a function or use other properties, you can use the detected body reference. is the “Sword” class a enemy with health?

if body is Sword:
    body.take_damage(damage)
1 Like

The reason I used /root/ is because I was experimenting. I’m still new to writing code and more times than not I don’t know how to write the syntax correctly.

So I realized that I had created the damaged_sword() function in a script attached to the AnimationPlayer Node, which is a child of the CharacterBody2D (The Sword Enemy). I moved the function damaged_sword() to the Enemy’s script.

Then I implemented your method: In the Bullet script → In the _ready() function:

func _ready() -> void:
	body_entered.connect(func (body: Node) -> void:
		body.get_node("HurtSwordAnimation")
		if body is Sword:
                body.damaged_sword()

It seems to be working as it should. Thanks a lot for your help. Believe it or not, the fact that you gave me those hints helped me see what I was doing incorrectly so thanks again :+1:

1 Like