概要
Godotには主要な2Dアニメーションシステムが2つあります。AnimatedSprite2Dはスプライトフレームアニメーション専用、AnimationPlayerは複合的なプロパティアニメーションに使用します。
最初は「なぜ2つもアニメーションシステムがあるのか?」と疑問でした。Unityから来た私は、最初はAnimationPlayerで全てをやろうとしていましたが、実際に使ってみると、それぞれに明確な役割があることが分かりました。特にキャラクターの歩行アニメにはAnimatedSprite2Dが圧倒的に便利で、複雑なエフェクトにはAnimationPlayerが最適でした。

各システムの特徴
AnimatedSprite2D
- 用途: スプライトシートからのフレームアニメーション
- 得意: キャラクターの歩行、攻撃モーション
- 設定: SpriteFramesリソースで管理
- 制御: シンプルなplay/stop
AnimationPlayer
- 用途: 複数プロパティの同時制御
- 得意: 位置、回転、スケール、色の変化
- 設定: アニメーショントラックで管理
- 制御: 高度なブレンドや遷移が可能
基本的な使い方
AnimatedSprite2Dの実装
# Player.gd
extends CharacterBody2D
@onready var animated_sprite = $AnimatedSprite2D
func _physics_process(delta):
# 移動アニメーション
if velocity.length() > 0:
if velocity.x > 0:
animated_sprite.play("walk_right")
animated_sprite.flip_h = false
elif velocity.x < 0:
animated_sprite.play("walk_right")
animated_sprite.flip_h = true
elif velocity.y > 0:
animated_sprite.play("walk_down")
elif velocity.y < 0:
animated_sprite.play("walk_up")
else:
animated_sprite.stop()
animated_sprite.frame = 0
AnimationPlayerの実装

# Sword.gd
extends Node2D
@onready var animation_player = $AnimationPlayer
@onready var sprite = $Sprite2D
func attack(direction: String):
match direction:
"right":
animation_player.play("swing_right")
"left":
animation_player.play("swing_left")
"up":
animation_player.play("swing_up")
"down":
animation_player.play("swing_down")
組み合わせて使う例
キャラクターと武器のアニメーション
# Player.gd
extends CharacterBody2D
@onready var sprite = $AnimatedSprite2D
@onready var weapon_animator = $Weapon/AnimationPlayer
func _process(delta):
if Input.is_action_just_pressed("attack"):
perform_attack()
func perform_attack():
var facing = get_facing_direction()
# キャラクターのアニメーション
sprite.play("attack_" + facing)
# 武器のアニメーション(位置と回転)
weapon_animator.play("swing_" + facing)
# アニメーション終了待ち
await sprite.animation_finished
sprite.play("idle_" + facing)
AnimationPlayerの高度な使い方
複数プロパティの同時制御
# AnimationPlayerで以下を同時に制御:
# - 位置(position)
# - 回転(rotation)
# - スケール(scale)
# - 色(modulate)
# - 可視性(visible)
# - カスタムメソッド呼び出し
func create_death_animation():
var animation = Animation.new()
var track_index = animation.add_track(Animation.TYPE_VALUE)
# スケールを縮小
animation.track_set_path(track_index, ".:scale")
animation.track_insert_key(track_index, 0.0, Vector2(1, 1))
animation.track_insert_key(track_index, 0.5, Vector2(0, 0))
# 回転
track_index = animation.add_track(Animation.TYPE_VALUE)
animation.track_set_path(track_index, ".:rotation")
animation.track_insert_key(track_index, 0.0, 0)
animation.track_insert_key(track_index, 0.5, PI * 2)
# アニメーションを登録
$AnimationPlayer.add_animation("death", animation)
メソッドトラックの活用
# AnimationPlayerからメソッドを呼び出す
func spawn_effect():
var effect = preload("res://Effects/HitEffect.tscn").instantiate()
get_parent().add_child(effect)
effect.global_position = global_position
func play_sound():
$AudioStreamPlayer.play()
# AnimationPlayerのメソッドトラックで
# 特定のフレームでこれらの関数を呼び出す
使い分けの指針
AnimatedSprite2Dを選ぶべき場合
- スプライトシートがメイン
- フレーム単位のアニメーション
- シンプルな再生制御で十分
- キャラクターモーション
AnimationPlayerを選ぶべき場合
- 複数のプロパティを制御
- タイミング精密な制御が必要
- エフェクトやUIアニメーション
- カットシーン
実装例:コンボシステム
# ComboAttack.gd
extends Node2D
@onready var sprite = $AnimatedSprite2D
@onready var hitbox_animator = $HitboxAnimator
@onready var effect_animator = $EffectAnimator
var combo_count = 0
func attack():
combo_count = (combo_count % 3) + 1
# スプライトアニメーション
sprite.play("combo_" + str(combo_count))
# ヒットボックスの移動と有効化
hitbox_animator.play("hitbox_combo_" + str(combo_count))
# エフェクト
if combo_count == 3:
effect_animator.play("special_effect")
パフォーマンスの比較
項目 | AnimatedSprite2D | AnimationPlayer |
---|---|---|
メモリ使用 | 高(全フレーム保持) | 低(キーフレームのみ) |
CPU負荷 | 低 | 中(補間計算) |
設定の手間 | 簡単 | やや複雑 |
柔軟性 | 限定的 | 非常に高い |
Unityとの比較
Unity Animator ≈ Godot AnimationPlayer
- 状態機械 → AnimationTree(Godotの別機能)
- アニメーションクリップ → Animationリソース
- アニメーター → AnimationPlayer
Unity Animation ≈ Godot AnimatedSprite2D
- スプライトアニメーション特化
- より直感的な操作
ベストプラクティス
- 役割分担: キャラクター本体はAnimatedSprite2D、エフェクトはAnimationPlayer
- 命名規則: アニメーション名を統一("idle_left", "walk_left", "attack_left")
- フレームレート: AnimatedSprite2DのFPSを適切に設定(通常8-12fps)
- リソース管理: 大きなスプライトシートは分割を検討
トラブルシューティング
アニメーションが再生されない
# AnimatedSprite2Dの確認
print(animated_sprite.sprite_frames) # nullでないか
print(animated_sprite.animation) # 存在するアニメーション名か
# AnimationPlayerの確認
print(animation_player.get_animation_list()) # アニメーション一覧
print(animation_player.is_playing()) # 再生中か
ちらつきや途切れ
- AnimatedSprite2D: ループ設定を確認
- AnimationPlayer: 補間モードを調整
実装して学んだこと
この2つのアニメーションシステムを使い分けられるようになってから、ゲームのアニメーション品質が大幅に向上しました。AnimatedSprite2Dはキャラクターの生きた動きを簡単に実現でき、AnimationPlayerは精密なタイミングと複数要素の同期が必要なエフェクトを作れます。
特に印象的だったのは、メソッドトラック機能です。AnimationPlayerでアニメーションの特定のフレームで関数を呼び出せるので、「攻撃の瞬間にダメージ判定」「歩行時に足音」など、ゲームロジックとアニメーションを緊密に連携させられます。
また、両方を組み合わせることで、キャラクター自体はAnimatedSprite2Dで自然に動かしつつ、武器やエフェクトはAnimationPlayerで精密に制御するという、非常に柔軟で効果的なアニメーションシステムを構築できるようになりました。