AnimationPlayerで位置を変更する際、現在の場所から相対的な動きをしたい。

Godotバージョン

4.3

OSとそのバージョン

windows 11 23H2

使用言語

GDScript

内容

GodotのAnimationPlayerを用いて、現在の座標を基準に画像等を動かすことはできるでしょうか?(現在のX座標から+10、Y座標から-20みたいな感じ)
子シーンの中にあるAnimationPlayerの場合でも、親シーンの座標で表示されるようで困っています。エフェクトをアニメーションプレイヤーで表示しようとしています。子シーンでは座標(0,0)にエフェクトを表示すれば他のパーツとうまく組み合わさって表示されますが、それを親シーン上で再生すると、子シーンの親シーン上での座標とは関係なく、親シーンの(0,0)にエフェクトのみが移動してしまいます。
また、AnimationPlayerでそのような処理ができない場合は、何か別の手段があるでしょうか?

子シーンのノードの構成を
.
Player(AnimatedSprite)
└ AnimationPlayer
└Effect(AnimatedSprite)

から
Player(AnimatedSprite)
├AnimationPlayer
├Effect(AnimatedSprite)

に変えると、エフェクトが子シーンの位置を基準に動くようになり、想像通りの動きをするようになりました。

今回の場合は、プレイヤーの子ノードの位置が動くアニメーションだったのでよかったのですが、例えばこれが「プレイヤーの攻撃のアニメーションに合わせてプレイヤー自身の座標が、現在の座標から前に50進む」みたいな実装を行いたいときはどのようにしたら良いでしょうか?
やはり「メソッド呼び出しトラック→tweenで移動」のような処理にするしかないのでしょうか?

ここで既に解答していますが、本格的に core に実装するためにはいくつか根本的な実装が必要になります。

現在ユーザーが実行可能な簡易的な解決方法はそこに書いたように、

  1. ダミーのトラックを作成
  2. 1フレームごとにダミートラックの値の差を delta として抽出
  3. ターゲットとなるプロパティにその delta を加算

というようなものなります。

例えば 1 秒で x 座標を 50 移動したいのであれば、

@export var move: Vector2

というように move というダミーのプロパティを適当なオブジェクトに追加し、アニメーションで 0 秒地点に Vector2(0, 0)、1 秒地点に Vector2(50, 0) というキーを打ちます。

アニメーションの適用は AnimationPlayer.mixer_applied シグナルで検知できるためシグナルを接続し、

var prev_move: Vector2

func _on_mixer_applied() -> void:
    var delta: Vector2 = dummy_node.move - prev_move 
    target_node.position += delta
    prev_move = dummy_node.move

というように書けます。

ただしこの時、相対アニメーションと相対でないアニメーションはブレンドできない点と、角度と位置を両方動かす場合にはアキュムレーター等の実装が必要な可能性がある点に注意してください。

ありがとうございます!
やっぱり相対移動はエンジン自体は未対応で工夫が必要なんですね…

工夫とはいえ、もしエンジンが対応するとしても同じようなコードを core の中に持つだけになる(と個人的には思っている)ので上記のコードが一番素直な実装方法だとは思います

このトピックは最後の返信から 60 分が経過したので自動的にクローズされました。新たに返信することはできません。