Yes, you can absolutely do layered animations in Godot using the spine-godot runtime! This is done using animation tracks, which allow you to play multiple animations on top of each other.
How Animation Tracks Work
When you play multiple animations on different tracks, animations on higher tracks override the effects of animations on lower tracks if they key the same skeleton properties. This is perfect for your use case:
- Track 0: Idle animation (looping)
- Track 1: Blink animation (plays on top)
- Track 2: Talk animation (plays on top)
Example Code
Here's how you would set this up in GDScript:
extends SpineSprite
func _ready():
var animation_state = get_animation_state()
# Play idle animation on track 0 (looping)
animation_state.set_animation("idle", true, 0)
# Play blink animation on track 1 (looping)
# Only the parts keyed in "blink" will override "idle"
animation_state.set_animation("blink", true, 1)
# When you want to trigger talking:
# animation_state.set_animation("talk", true, 2)
For Random Blinking
To randomize blinking, you could use a timer:
extends SpineSprite
var animation_state
func _ready():
animation_state = get_animation_state()
animation_state.set_animation("idle", true, 0)
# Start random blink timer
_schedule_next_blink()
func _schedule_next_blink():
var random_delay = randf_range(2.0, 5.0) # Blink every 2-5 seconds
await get_tree().create_timer(random_delay).timeout
# Play blink animation on track 1
animation_state.set_animation("blink", false, 1)
# Schedule next blink after this one completes
_schedule_next_blink()
Important Setup in Spine
For this to work properly, make sure in Spine:
- Your "blink" animation only keys the elements that change (like eyelid bones/slots)
- Your "talk" animation only keys the mouth-related bones/slots
- This way they won't interfere with other parts of the idle animation
You can find more details in the spine-godot documentation under the "Animating a SpineSprite" section: https://esotericsoftware.com/spine-godot#Animating-a-SpineSprite