I have created a base scene that I intend to use for all human characters of my game. I am using an AnimatedSprite
where I defined different animations for the different positions of the character, all using a texture that contains all the frames.
This works for a specific character, but now I would like to create other characters. Since I am using a character generator, all the sprite sheets are basically the same, but with different clothes, accessories, etc. I would like to avoid replicating the animation definitions for the other characters. I could achieve that by setting a different texture on each instance of the scene, but I can't find a way to do it.
If I edit the tscn file and set a different image, it does what I want.
I tried updating the atlas
property of the animation frames, but doing that affects all instances of the scene:
func update_texture(value: Texture):
for animation in $AnimatedSprite.frames.animations:
for frame in animation.frames:
frame.atlas = value
I also tried cloning a SpriteFrames
instance, by calling duplicate(0)
, updating it with the above code, then setting $AnimatedSprite.frames
, but this also updates all instances of the scene.
What is the proper way to change the texture of a specific instance of AnimatedSprite?
I found a solution. The problem was that the duplicate
method does not perform a deep clone, so I was having references to the same frame instances.
Here's my updated version:
func update_texture(texture: Texture):
var reference_frames: SpriteFrames = $AnimatedSprite.frames
var updated_frames = SpriteFrames.new()
for animation in reference_frames.get_animation_names():
if animation != "default":
updated_frames.add_animation(animation)
updated_frames.set_animation_speed(animation, reference_frames.get_animation_speed(animation))
updated_frames.set_animation_loop(animation, reference_frames.get_animation_loop(animation))
for i in reference_frames.get_frame_count(animation):
var updated_texture: AtlasTexture = reference_frames.get_frame(animation, i).duplicate()
updated_texture.atlas = texture
updated_frames.add_frame(animation, updated_texture)
updated_frames.remove_animation("default")
$AnimatedSprite.frames = updated_frames