PeriodicタイプGameplayEffectの適用回数の取得について

いつもお世話になっております。

ゲームプレイエフェクトの期間ありで一定時間ごとに実行されるタイプの挙動について質問をさせて頂きます。

ゲーム中にて、継続ダメージ(Dotダメージ)を作成するにあたり、GEにて HasDuration と Period を設定し、

一定時間ごとにダメージを与えるGEアセットを作成しました。

ここでこのGEの動作中に残りの与ダメージ値を取得したいのですが、FActiveGameplayEffectでは適用回数が取得できないため

残り時間とダメージ値をもとに計算で残りダメージ値を算出したのですがやはり実行タイミングの問題なのかズレがでてしまいます。

// DOTダメージの残り予定ダメージ値を計算する
const FActiveGameplayEffect* _AGE = _ASC->GetActiveGameplayEffect(_Handle);
if (_AGE) {
	int32 _Damage = 0;
	float _Remain = _AGE->GetTimeRemaining(GetWorld()->GetTimeSeconds());
	float _Period = _AGE->GetPeriod();
	int32 _OneDmg = (int32)_AGE->Spec.GetSetByCallerMagnitude(FGameplayTag::RequestGameplayTag(FName("Data.Damage")));

	// 残りのダメージ値合計の計算
	_Damage = (int32)(FMath::CeilToInt(_Remain / _Period) * _OneDmg);

	UE_LOG(LogTemp, Log, TEXT("Remain=%f, Health=%f, Damage=%d"), _Remain, GetHealth(), _Damage);
}


例としてDurationが4秒で、1秒ごとに適用設定、ダメージ値が10、ヘルスが100の状態でログを出してみると

残り時間が3秒を切ったタイミングで予定ダメージ値が計算上30になりますがこの時点ではヘルスにはまだ反映されていないためズレがでております。

LogTemp: Remain=3.003804, Health=100.000000, Damage=40

LogTemp: Remain=2.985813, Health=100.000000, Damage=30 // ←このタイミングでズレがでる

LogTemp: Remain=2.966654, Health=90.000000, Damage=30

LogTemp: Remain=2.948841, Health=90.000000, Damage=30

この問題は適用回数が取得できないためだと思うのですが、適用回数を取得する方法が見当たりません。

こちらを正確に取得する方法はありますでしょうか。

お手数ですがよろしくご確認をお願いいたします。

再現手順
ゲームを実行し、[1]キーを押すと継続ダメージのゲームプレイエフェクト(GE_DotDamage)が実行され残り時間と現時点のヘルスと残りの予定与ダメージ値のログが出力されます。

サンプルのGEはDuration4秒で1秒ごとに10ダメージを適用する設定で、ヘルスの初期値が100になっています。​

お世話になっております。

ご質問ありがとうございます。

残念ながら、PeriodicタイプのGameplayEffectの適用回数を調べる直接的な方法はございません。

経過時間などから逆算するアプローチが次善の策となりますが、すでにお試しいただいたように、実際の適用状況と齟齬がない精度で回数を計算することは非常に困難です。

他のアプローチとしては、DoTの予想される累計与ダメージ量をあらかじめ「予告ダメージ」的にアトリビュートとして付与し、この予告量を減らしながらダメージ適用を行うという方法が考えられます。

そのほかの代替策について、現在社内で確認を行っておりますので、もう少々お時間をいただけますと幸いです。

以上、よろしくお願いいたします。

お世話になっております。

Peridicタイプの実行回数の取得ですが、カウント用のGameplayEffectComponent を用意し、SetByCaller で変数を保持して、OnGameplayEffectExecuted() にて更新するという方法で回数を取得することができました。

(やや冗長な方法な気がしますが)

一旦この方法でやってみたいと思います。

引き続き、良い方法があればお教えください。

よろしくお願いいたします。

ご返答ありがとうございます。

やはり直接取得する方法はないようですね。

>他のアプローチとしては、DoTの予想される累計与ダメージ量をあらかじめ「予告ダメージ」的にアトリビュートとして付与し、

>

そのアプローチは思いつきませんでした。

確かに複数DOTだとしてもこのアトリビュートにまとめることができそうですし、同期を考慮しないでもいいローカル限定ならアトリビュートでなくともプロパティでも良さそうです。

あと問題がありそうなのは途中でDOT処理がキャンセルされるようなケースでしょうか。

こちらで考えた方法は GameplayEffectComponentを継承して、OnGameplayEffectExecuted()が実行された回数を渡せないか、というものでした。

この方法はこの実行時情報の渡し先をどうするか、で難航してしまいました。

>そのほかの代替策について、現在社内で確認を行っておりますので、もう少々お時間をいただけますと幸いです。

>

お手数ですがよろしくお願いいたします。

お世話になっております。

ご検証ありがとうございます。

社内確認の結果、別のアプローチとして、Periodic タイプの Gameplay Effect が実行されるたびに呼ばれるデリゲート

・OnPeriodicGameplayEffectExecuteDelegateOnSelf および

・OnPeriodicGameplayEffectExecuteDelegateOnTarget

を利用し、手動で実行回数をカウントする方法も有効ではないか、という意見がございました。

一度ご確認いただけますと幸いです。​

以上、よろしくお願いいたします。​

お世話になっております。

ご提案頂きましたデリゲートで動作を確認してみましたところPeridicの実行タイミングで取得できました。

ただ、AbilitySystemComponentに登録しているので当然ですが、他の適用中のPeridicタイプなゲームプレイエフェクトでも実行されるため目的なものかをハンドル等で判別する必要がありました。

前のカウント用GameplayEffectComponentを用意する方法と実行タイミングは変わらないようですし、用途で使い分けるのもアリかもしれません。

ご回答ありがとうございました。

また何かありましたら質問させて頂きますのでよろしくお願いいたします。

ご確認をありがとうございました!

ご指摘のように、このアプローチはGameplay Effect単位のデリゲートではないため、コールバックを受けたあと自前で状況を分析する必要がございます。

それでは、本件は回答済みとしてクローズさせていただきます。

また何かご不明点や要確認事項などありましたら、お気軽にEPSをご利用ください。

以上、よろしくお願いいたします。