Invalid get index 'animation' (on base: 'Nil')

Godot Version

4.2.2.stable

Question

Hi, I’m still a newbie dev so maybe this question is a bit silly. I’m currently trying to implement the ghost trail when dashing.

when I deleted the func _on_ghost_timer_timeout(), everything is fine. I don’t know what I’m doing wrong. Any suggestion or help is greatly appreciated.

Thank you for reading this.

Here is my full code:

extends Node2D

const dash_delay = 0.4

@onready var duration_timer = $DurationTimer
@onready var ghost_timer = $GhostTimer



var can_dash = true
var sprite
var ghost_scene = preload("res://scene/DashGhost.tscn")

func start_dash(sprite, duration):
	self.sprite = sprite
	duration_timer.wait_time = duration
	duration_timer.start()
	ghost_timer.start()
	add_ghost()

func is_dashing():
	return !duration_timer.is_stopped()

func add_ghost():
	var ghost = ghost_scene.instantiate()
	get_parent().get_parent().add_child(ghost)

	var texture = sprite.sprite_frames.get_frame_texture(sprite.animation, sprite.frame)
	ghost.texture = texture
	ghost.global_position = global_position
	ghost.flip_h = sprite.flip_h
	
	
func end_dash():
	ghost_timer.stop()
	can_dash = false
	await get_tree().create_timer(dash_delay).timeout
	can_dash = true

func _on_duration_timer_timeout():
	end_dash()

func _on_ghost_timer_timeout():
	add_ghost()

You never assign sprite, you never call start_dash, or you don’t ensure you’ve called it when add_ghost is called

1 Like

this line, the error at, the first parameter of get_frame_texture is stringname of the animation you wanted to get from the Sprite Frames, so it shouldnt be sprite.animation, but instead something like "dash"

2 Likes

I don’t think that is the solution to it. Appreciated nonetheless

Tried.
The error is now Invalid get index ‘frame’ (on base: 'Nil")

You need to make sure start_dash is called before add_ghost, or sprite will be empty

1 Like

yea forgot to say you need to specify which index in the animation you wanted to get, not the .frame

so something like

var texture = sprite.sprite_frames.get_frame_texture("dash", 0)
1 Like

That won’t fix it, the sprite needs to be assigned, it’s used below too, and in the same call, so it’s not correct

1 Like

can you give me a example of how to do it?

I don’t know your project, you should not start the ghost timer until you’ve started the dash I think, that would be the simplest solution

1 Like

You are correct. The sprite is not assigned continuously. It work some time and break sometime. Maybe it is because of the delay?

Without seeing the rest of your code I have no idea, because start_dash is never called in the sample you showed

1 Like

Here is the script of the player. You can see when the start_dash is called in func player_movement_animate

extends CharacterBody2D

const max_speed = 100
const accel = 1000
const dashAccel = 1200
const friction = 600
const dash_speed = 1000 * 5
const dash_duration = 0.2


var player_stat


@onready var Dash = $Dash
@onready var sprite = $AnimatedSprite2D

func _physics_process(delta):
	player_movement_and_animate(delta)
	

func player_movement_and_animate(delta):
	var input = Input.get_vector("left", "right", "up", "down")
	input = input.normalized()
	
	if Input.is_action_just_pressed("dash") && Dash.can_dash && !Dash.is_dashing():
		Dash.start_dash(sprite, dash_duration)
		
		
	var speed = dashAccel if Dash.is_dashing() else accel
		
	if input.x == 0 and input.y == 0:
		if velocity.length() > (friction * delta):
			velocity -= velocity.normalized() * (friction * delta)
		else:
			velocity = Vector2.ZERO
			$AnimatedSprite2D.flip_h = false
			if player_stat == "front":
				$AnimatedSprite2D.play("Idle front")
			elif player_stat == "back":
				$AnimatedSprite2D.play("Idle back")
			elif player_stat == "side":
				$AnimatedSprite2D.play("Idle side")
			elif player_stat == "side_f":
				$AnimatedSprite2D.flip_h = true
				$AnimatedSprite2D.play("Idle side")
	else:
		$AnimatedSprite2D.flip_h = false
		velocity += (input * speed * delta)
		velocity = velocity.limit_length(500)
		if Dash.is_dashing():
			if player_stat == "front":
				$AnimatedSprite2D.play("Dash front")
			elif player_stat == "back":
				$AnimatedSprite2D.play("Dash back")
			elif player_stat == "side":
				$AnimatedSprite2D.play("Dash Side")
			elif player_stat == "side_f":
				$AnimatedSprite2D.flip_h =  true
				$AnimatedSprite2D.play("Dash Side")
	if !Dash.is_dashing():
		velocity = velocity.limit_length(max_speed)
		
		if input.y == -1:
			$AnimatedSprite2D.play("Move back")
			player_stat = "back"
		if input.y == 1:
			$AnimatedSprite2D.play("Move front")
			player_stat = "front"
		if input.x == -1:
			$AnimatedSprite2D.flip_h = true
			$AnimatedSprite2D.play("Move side")
			player_stat = "side_f"
		if input.x == 1:
			$AnimatedSprite2D.play("Move side")
			player_stat = "side"
			
		if input.x > 0.5 and input.y < -0.5:
			$AnimatedSprite2D.play("Move back")
			player_stat = "back"
		if input.x > 0.5 and input.y > 0.5:
			$AnimatedSprite2D.play("Move front")
			player_stat = "front"
		if input.x < -0.5 and input.y < -0.5:
			$AnimatedSprite2D.play("Move back")
			player_stat = "back"
		if input.x < -0.5 and input.y > 0.5:
			$AnimatedSprite2D.play("Move front")
			player_stat = "front"
	
	move_and_slide()

I have managed to correct my mistake by add an if statement and adding the var script as an input into this func:

func add_ghost(sprite):
	if sprite:
		var ghost = ghost_scene.instantiate()
		get_parent().get_parent().add_child(ghost)

		var texture = sprite.sprite_frames.get_frame_texture(sprite.animation, sprite.frame)
		ghost.texture = texture
		ghost.global_position = sprite.global_position
		ghost.flip_h = sprite.flip_h

thanks you all for helping me

1 Like