SpawnActorで生成したNiagaraComponentでSyncGpuToCpuのArray DIを使うとensureが発生する

NiagaraSystemのUser Parameterに Gpu Sync Mode: SyncGpuToCpu の Array DI(例: Niagara Data Interface Array vector)を持つActorを SpawnActor で2体以上生成すると、GetNiagaraArrayVector() 等の呼び出し時に以下のensureが発生します。

ensure(PerInstanceData_GameThread.Num() <= 1);

// NiagaraDataInterfaceArrayImpl.h - FNDIArrayProxyImpl::GetArrayDataCopy()

レベルに複数手置きした場合は発生しません。

SpawnActorで生成した場合、OverrideParameters 内のDIオブジェクトの GetOuter() がCDO由来のままで、コンポーネント固有のコピーが作成されていないようで、

複数インスタンスが同一DIのProxyを共有し、PerInstanceData_GameThread に複数のSystemInstanceが登録されるようです。

UNiagaraComponent::FixDataInterfaceOuters() がDIのOuter確認と固有コピー作成を担当していますが、呼び出し箇所がPostLoad(デシリアライズ時)とエディタ用パスに限定されており、ランタイムのSpawnActor→Register→Activateパスでは実行されていないようです。

上記を回避するため、BeginPlay内でActivate前に FixDataInterfaceOuters() の最終ループ相当を手動実行するようにするとensureが発生しなくなることを確認しています。

ーー

// UNiagaraComponent::FixDataInterfaceOuters() の最終ループのコピー

const EObjectFlags DataInterfaceObjectFlags = RF_Transactional;

FNiagaraParameterStore& OverrideParams = NiagaraComponent->GetOverrideParameters();

for (int32 i = 0; i < OverrideParams.GetDataInterfaces().Num(); ++i)

{

UNiagaraDataInterface\* OverrideParameterDataInterface \= OverrideParams.GetDataInterface(i);

if (OverrideParameterDataInterface !\= nullptr \&\& OverrideParameterDataInterface\-\>GetOuter() !\= NiagaraComponent)

{

    UNiagaraDataInterface\* FixedDataInterface \= NewObject\<UNiagaraDataInterface\>(NiagaraComponent, OverrideParameterDataInterface\-\>GetClass(), NAME\_None, DataInterfaceObjectFlags);

    if (FixedDataInterface !\= nullptr)

    {

        OverrideParameterDataInterface\-\>CopyTo(FixedDataInterface);

        OverrideParams.SetDataInterface(FixedDataInterface, i);

    }

}

}

ーー​

上記問題につきまして、

・これは既知の問題でしょうか?

・InitializeSystem() 等で FixDataInterfaceOuters() が呼ばれるべきという認識で合っていますか?

・上記ワークアラウンドで問題ありませんでしょうか?

他に対応方法等ありましたらご教授いただけると幸いです。

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

[Attachment Removed]

大変お待たせしております。英語のグループにご投稿なされていたのでルーティングに時間が掛かってしまいました。

調査に取り掛かりますのでもう少々お待ちください。

[Attachment Removed]

再現を試みようと思っておりますが、GetArrayDataCopyでのPerInstanceData_GameThread数が1となっていてクラッシュしていないようです。

再現手順には以下の方法で行っておりますが差があればご指摘ください。

  1. NiagaraSystemを新規作成 RadialBurstテンプレートを利用
  2. UserParameterに Array Float 3のデータインターフェイスを追加、Sync GPU to CPU に設定、MaxElementはとりあえず10に設定
  3. GPUSimのエミッタのEmitterUpdateにScratch Moduleを追加して、モジュール内で 入力のVector Array に対してAddを呼び出す
  4. Scratch ModuleのインプットにUserParameterをバインド
  5. BPを新規作成してNiagaraParticleSystemComponentを追加作成したNiagaraSystemを設定
  6. BeginPlayで NiagaraGetVectorArray で配列を取得
  7. レベルブループリントのTickイベントで定期的に 手順後5のアクターを2体ずつSpawnするようにする
  8. PIEを実行

もし再現プロジェクトがすでにあればご共有いただけますとスムーズに調査が可能ですのでご検討ください。

以下のEPSケースはPerInstanceData_GameThreadが2以上になってEnsureが発火している問題で非常に類似性が高いですが、再現手順やEnsureの位置が違うため同じワークアラウンドが適用できるか判断に至っていません。

[Content removed]

[Attachment Removed]

再現調査ありがとうございます。

こちらでもプレーンな状態のUE5.8とBPのみのプロジェクトで同様の手順にて再現を試みましたが、再現しておりません。

こちらの環境ではネットワーク対応があるため、レプリケーションでパラメータが同期されるのを待ってからNiagaraSystemのActivate(true)を呼び出している点が若干異なるかと考え、AutoActivateをOFFにし遅延後にActivate(true)する構成も試してみましたが、ログなどでensureは確認できませんでした。

とりあえずは先のケースで提示したワークアラウンド(FixDataInterfaceOutersの最終ループ相当を手動実行)で回避できておりますので、特に深刻な問題が考えられなければそちらで対応したいと思います。

本件はクローズしていただいて問題ございません。

ご対応ありがとうございました。

[Attachment Removed]