fix: animation debug + F1 third-person camera

SkinnedPlayerModel:
- Added _print_tree debug to see GLB scene structure at runtime
- Auto-play Idle animation on load
- Added periodic debug output for animation state
- Only change animation when target differs from current

Third-person camera:
- F1 toggles between FPS and third-person view
- Third-person camera positioned behind/above player
- Smooth follow with lerp
- Camera tracks player position each frame
This commit is contained in:
2026-06-22 19:55:54 -04:00
parent e84a9d641a
commit b1aec93fd5
2 changed files with 113 additions and 29 deletions
+49 -28
View File
@@ -8,7 +8,7 @@ class_name SkinnedPlayerModel
var skeleton: Skeleton3D
var animation_player: AnimationPlayer
var animation_tree: AnimationTree
var _anim_debug_timer: float = 0.0
func _ready() -> void:
if model_path != "":
@@ -31,18 +31,39 @@ func load_model(path: String) -> void:
add_child(scene)
# Find skeleton and animation player
skeleton = find_skeleton(scene)
animation_player = find_animation_player(scene)
# Debug: print the full scene tree
print("SkinnedPlayerModel: scene tree after instantiation:")
_print_tree(scene, 0)
# Find animation player — search entire tree including the scene root itself
animation_player = find_animation_player(self)
if not animation_player:
animation_player = find_animation_player(scene)
skeleton = find_skeleton(self)
if not skeleton:
skeleton = find_skeleton(scene)
if animation_player:
print("SkinnedPlayerModel: loaded '%s' with %d animations" % [
path, animation_player.get_animation_list().size()
])
for anim in animation_player.get_animation_list():
print(" - %s" % anim)
var anim_list = animation_player.get_animation_list()
print("SkinnedPlayerModel: found AnimationPlayer with %d animations:" % anim_list.size())
for anim in anim_list:
print(" - %s (length: %.2f)" % [anim, animation_player.get_animation(anim).length])
# Auto-play idle
if animation_player.has_animation("Idle"):
animation_player.play("Idle")
print("SkinnedPlayerModel: playing 'Idle'")
elif anim_list.size() > 0:
animation_player.play(anim_list[0])
print("SkinnedPlayerModel: playing first anim: %s" % anim_list[0])
else:
print("SkinnedPlayerModel: no animation player found")
print("SkinnedPlayerModel: WARNING - no AnimationPlayer found in scene tree")
func _print_tree(node: Node, depth: int) -> void:
var indent = " " * depth
print("%s%s (%s)" % [indent, node.name, node.get_class()])
for child in node.get_children():
_print_tree(child, depth + 1)
func find_skeleton(node: Node) -> Skeleton3D:
if node is Skeleton3D:
@@ -72,6 +93,15 @@ func _process(delta: float) -> void:
if not animation_player:
return
# Debug: print animation state occasionally
_anim_debug_timer += delta
if _anim_debug_timer > 2.0:
_anim_debug_timer = 0.0
if animation_player.is_playing():
print("SkinnedPlayerModel: playing '%s' (pos: %.2f)" % [animation_player.current_animation, animation_player.current_animation_position])
else:
print("SkinnedPlayerModel: NOT playing any animation")
# Get movement state from the state machine
var sm = get_parent().get_node_or_null("MovementStateMachine")
if not sm:
@@ -84,25 +114,16 @@ func _process(delta: float) -> void:
var vel = sm.player.velocity
speed = Vector2(vel.x, vel.z).length()
# Only change animation if it's different from current
var target_anim = "Idle"
match state:
"ground", "idle":
if speed > 1.0:
play_animation("Run")
else:
play_animation("Idle")
"air":
play_animation("Idle")
"crouch":
play_animation("Idle")
"slide":
play_animation("Run")
"wall_run":
play_animation("Run")
"wall_cling":
play_animation("Idle")
"grapple":
play_animation("Run")
"dash":
play_animation("Run")
target_anim = "Run"
"slide", "wall_run", "grapple", "dash":
target_anim = "Run"
_:
play_animation("Idle")
target_anim = "Idle"
if animation_player.current_animation != target_anim or not animation_player.is_playing():
play_animation(target_anim)