Having an issue with using sprite resources on AnimatedSprite2D (Godot 4 3 Stable)

Godot Version

Godot 4 3 Stable

Question

My goal was to have it so, depending on the level, the “magic arrow” would have different sprites.
This is because I wanted to associate the arrow’s sprites with the player character (Who I plan to give actual sprites later on).
The idea being that the game has 2 player characters (Same code, different sprites) and the magic arrows also have different colors, based on the respective characters.

But for some reason, the sprites that show up are the ones as selected in the editor and not the ones related to the export var code.
So I can’t give the arrow specific sprite resources depending on the level.
These are the lines of code I assume are relevant:

@onready var sprite = $AnimatedSprite2D

Which allows the node to be referenced in code.

@export var arrowskin = “res://assets/sprites/play actor/leonarrow.tres”

Which creates a variable for the sprites’ resource.

func ready():
sprite.frames = load(arrowskin)

Which should allow the AnimatedSprite2D loading the respective resource being reference in the editor, depending on the level.
The code I used is because I believed it might be similar to how I did it in my previous game, which was on Godot 3.5.1.
But anyway, here’s the project: GitHub - EyeBallTank/Hirdrih-Technologic: A game about the world of Hirdrih
And the relevant scenes are:

Regardless, any help is appreciated.

1 Like

Hi eyeballtank!

If I create an export variable in a script I usually assign another value to that variable later using the editor. That’s kind of the purpose of export variables. So if you tell me what got selected in the editor shows up in the export variables, that’s the outcome I would expect.

I would expect this to also be overridden by the in-editor assignment. Your in-code assignment is merely a default.

From the Godot docs on @export annotations:

An exported variable must be initialized to a constant expression or have a type specifier in the variable. […]

One of the fundamental benefits of exporting member variables is to have them visible and editable in the editor.

Why do you not just create two variables (and nodes, and scenes) for each of your two sprites and switch them out in an if statement within your code. You could for example toggle their visibility at first (see code below).

var sprite1 = $AnimatedSprite2D_ONE
var sprite2 = $AnimatedSprite2D_TWO
var arrowskin = "res://assets/sprites/play actor/leonarrow1.tres"
var arrowskin = "res://assets/sprites/play actor/leonarrow2.tres"

func ready():
	sprite1.sprite_frames = load(arrowskin1)
	sprite2.sprite_frames = load(arrowskin2)

# somewhere later in your code:
func some_function():
	if player.number == 1:
		sprite1.visible = true
		sprite2.visible = false
	else:
		sprite1.visible = false
		sprite2.visible = true

Would that do what you are looking for? :four_leaf_clover:

1 Like

Would that do what you are looking for? :four_leaf_clover:

Not sure because the method of resources I was trying to implement is one that I also want to try with the player character (Since I plan 2 characters) and other objects in the world (Because this game ideally is about travelling through different world and stuff like pickups and objects would have different themes).

To give an example: In my previous game (Project Nortubel, Godot 3.5.1), I used that method of using spriteset resources for both level objects like switches to interact with and the protagonists themselves (There’s 6 protagonists in that game, 3 being the main player character and the other 3 being the “companion”; So throughout the levels, the game switched “skins” to make it feel like you were changing playable characters though different levels).
And Nortubel, like I plan with Hirdrih, was also about going through different worlds, so some objects like level switches had themes dedicated to certain chapters.

Because stuff like the code and frames/animations in the AnimatedSprite2D scene were the same of each resource, it’s the resource itself that changes depending on how the export var is handled in the editor of certain levels.

This method in general, I recall learning it from a video series by HeartBeast, I believe.
I think it was his 2D pixel platformer series, where at some point, he taught how to add player skins.

So I was expecting something simple like that.
Because one thing is the resources (leonarrow and ottoarrow), but another is the “frames/animations” or whatever you call them, such as “basicmouse” and “clickedmouse”, which ideally are both shared by the resources, even if the resources should look different themselves.
In fact, this is the image of the arrows:

The yellow is for one character and the other is for the other character.
This idea even parallels how I handled the player skins in Nortubel.

So the idea was: In some levels, you get “leonarrow” (Which is the yellow arrow) and in others, you get “ottoarrow” (Which is the blue arrow).
And alongside that, the potential player sprites would reflect on that too.

The way I’ve done this in Godot 4.5 for changing player skins is with this sort of thing:

var animated_sprite_2d = $AnimatedSprite2D
var sprite_frames: SpriteFrames

sprite_frames = load("res://some_frames.tres")
animated_sprite_2d.set_sprite_frames(sprite_frames)

This successfully replaces the frames I set with the export variable in the editor.

You might get what you need by changing your “sprite.frames = …” to “sprite.set_sprite_frames()”.

I tried this but nothing really changed.

This is how I implemented: