Godot Version
4.4.1-stable
Question
I’m making a metroidvania game for Metroidvania Month 28 Game Jam. (It ends today.) When I export my game, if a CharacterBody2D in a level does not have Editable Children checked in the editor, the characters are not visible in the game. It’s really weird behavior, and I’m wondering if anyone else has seen it or know what causes it?
The biggest problem this causes, is I cannot initially spawn in characters like the player and bosses, because setting the value of editable children in code before or after adding them to the scene tree isn’t enough.
My only guess is that I have a tool script attached to the AnimatedSprite2D nodes that loads all the images for me from a directory so I don’t have to. It loads all the sprite frames for a character in about a second, instead of me doing it by hand. It has saved me immeasurable time.
@tool
class_name ChibiAnimatedSprite2D extends AnimatedSprite2D
const DEATH_ANIMATION = "dying"
const FALL_ANIMATION = "falling_down"
const HURT_ANIMATION = "hurt"
const IDLE_ANIMATION = "idle"
const IDLE_BLINKING_ANIMATION = "idle_blinking"
const JUMP_ANIMATION = "jump_loop"
const JUMP_START_ANIMATION = "jump_start"
const KICK_ANIMATION = "kicking"
const RUN_SLASH_ANIMATION = "run_slashing"
const RUN_THROW_ANIMATION = "run_throwing"
const RUN_ANIMATION = "running"
const ATTACK_ANIMATION = "slashing"
const JUMP_ATTACK_ANIMATION = "slashing_in_the_air"
const SHOOT_ANIMATION = "shooting"
const JUMP_SHOOT_ANIMATION = "shooting_in_the_air"
const SLIDE_ANIMATION = "sliding"
const THROW_ANIMATION = "throwing"
const JUMP_THROW_ANIMATION = "throwing_in_the_air"
const WALK_ANIMATION = "walking"
@export_dir var sprite_root_folder:
set(value):
sprite_root_folder = value
if sprite_frames:
sprite_frames = null
if value:
_load_sprite_frames()
## Returns true or false if this sprite has this animation.
func has_animation(animation_name: StringName) -> bool:
return sprite_frames.has_animation(animation_name)
func _load_sprite_frames() ->void:
#if sprite_frames is null, create a new instance
if not sprite_frames:
sprite_frames = SpriteFrames.new()
#delete default if it exists
sprite_frames.remove_animation(&"default")
#iterate through folders
var dir = DirAccess.open(sprite_root_folder)
if not dir:
return
var animation_list = dir.get_directories()
for animation_dir in animation_list:
var animation_name = animation_dir.get_file().to_snake_case()
sprite_frames.add_animation(animation_name)
sprite_frames.set_animation_speed(animation_name, 24.0)
#Set looping for looping animations
if animation_name.contains(IDLE_ANIMATION) or \
animation_name.contains("falling") or \
animation_name.contains("loop") or \
animation_name.contains("running") or \
animation_name.contains("sliding") or \
animation_name.contains("walking"):
sprite_frames.set_animation_loop(animation_name, true)
else:
sprite_frames.set_animation_loop(animation_name, false)
#change to the specific animation directory
dir.change_dir(animation_dir)
var file_list = dir.get_files()
var path = dir.get_current_dir() + "/"
#skip over .import files and uids and add the animation frames
for file in file_list:
if file.ends_with(".png"):
sprite_frames.add_frame(animation_name, load(path + file))
#drop back down a directory for the next loop
dir.change_dir("..")
#set the default animations
set_autoplay(IDLE_ANIMATION)
animation = IDLE_ANIMATION
Anyway, I have 11 hours until the jam concludes, and if anyone has any ideas on solving this problem, please let me know. Right now I’m working on a staging area for the player to be in when the game starts to pull it into the first level. (Needed so I don’t have two players when the player re-enters the first level from the second level.)