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]