在UE4中,如果想做一个编辑器检查功能,批量对所有NiagaraSystem资产进行检查,需要获取到特效内部发射器上的Module的某些具体配置,比如ParticleState上的 KillParticlesWhenLifetimeHasElapsed,用于检查是不是有一致发射,然后持续泄露的特效等。
因为要拿到Module上的信息,需要SystemViewModel,之前的做法是,在代码中 GetExistingViewModelForSystem,如果没有(也就是没有在编辑器中打开这个特效),则需要 Make一个然后Initialize,通过 SystemViewModel 获取 UNiagaraStackItemGroup,然后通过 GetUnfilteredChildrenOfType 获取 UNiagaraStackModuleItem,然后获取 UNiagaraStackFunctionInputCollection 数组,找到对应的 UNiagaraStackFunctionInputCollection,再根据参数的索引找到 UNiagaraStackFunctionInput,然后 >GetLocalValueStruct()->GetStructMemory() 的方式获取实际选项配置的值,进行判断。
想问下UE5中有没有什么优化,有什么更方便的批量检查,或者说单个资产检查配置的方式
[Attachment Removed]
RoryXY
(Xiao Yue)
2
你好,
UE5的Niagara Effect Type可以设置Validation Rules, 对不同类型的特效设置不同的资产检查规则. 除了如下默认的检查, 也很方便做规则扩展, 可以参考这篇文章看看.
[Image Removed]
[Attachment Removed]
比如我想获取不是NiagaraSystem上的参数,而是EmitterState 这个Module的 LoopBehavior配置,判断如果是Infinite,那么再看 ParticleState 上的 KillParticlesWhenLifetimeHasElapsed 是不是没选,这样来判断会不会有持续性的粒子泄露呢
[Attachment Removed]
RoryXY
(Xiao Yue)
4
如果用扩展Validation Rules的方式做, 5.7上, 可以在NiagaraValidationRules.h类似下面加一个规则:
UCLASS(Category = "Validation", DisplayName = "Validate Particle State")
class UNiagaraValidationRule_NoInfinitePariticles : public UNiagaraValidationRule
{
GENERATED_BODY()
public:
virtual void CheckValidity(const FNiagaraValidationContext& Context, TArray<FNiagaraValidationResult>& OutResults) const override;
};
NiagaraValidationRules.cpp中:
void UNiagaraValidationRule_NoInfinitePariticles::CheckValidity(const FNiagaraValidationContext& Context, TArray<FNiagaraValidationResult>& Results) const
{
UNiagaraStackModuleItem* SourceModule = Cast<UNiagaraStackModuleItem>(Context.Source);
if (SourceModule && SourceModule->GetIsEnabled())
{
TArray<UNiagaraStackFunctionInput*> ModuleInputs;
SourceModule->GetParameterInputs(ModuleInputs);
bool KillParticleWhenLifetimeHasElapsed = true;
for (UNiagaraStackFunctionInput* Input : ModuleInputs)
{
if (Input->GetInputParameterHandle().GetName() == FName("Kill Particles When Lifetime Has Elapsed"))
{
KillParticleWhenLifetimeHasElapsed = *(bool*)Input->GetLocalValueStruct()->GetStructMemory();
break;
}
}
if (KillParticleWhenLifetimeHasElapsed)
return;
UNiagaraStackModuleItem* EmitterStateModule = nullptr;
for (const TSharedRef<FNiagaraEmitterHandleViewModel>& EmitterHandleModel : Context.ViewModel->GetEmitterHandleViewModels())
{
if (EmitterHandleModel->GetIsEnabled() && EmitterHandleModel->GetEmitterViewModel() == SourceModule->GetEmitterViewModel())
{
TArray<UNiagaraStackModuleItem*> ModuleItems = NiagaraValidation::GetStackEntries<UNiagaraStackModuleItem>(EmitterHandleModel->GetEmitterStackViewModel());
for (UNiagaraStackModuleItem* Item : ModuleItems)
{
UNiagaraNodeFunctionCall& FuncCall = Item->GetModuleNode();
if (FuncCall.GetFunctionName() == FString("EmitterState"))
{
EmitterStateModule = Item;
break;
}
}
}
}
if (!EmitterStateModule)
return;
EmitterStateModule->GetParameterInputs(ModuleInputs);
for (UNiagaraStackFunctionInput* Input : ModuleInputs)
{
if (Input->GetInputParameterHandle().GetName() == FName("Loop Behavior") && *(int32*)Input->GetLocalValueStruct()->GetStructMemory() == 0)
{
FNiagaraValidationResult Result(ENiagaraValidationSeverity::Warning, LOCTEXT("NoInfiniteParticlesSummary", "check loop behavior"), LOCTEXT("NoInfiniteParticlesDescription", "paricles reaching lifetime not killed in ParticleState"), Input);
Results.Add(Result);
break;
}
}
}
}
然后把这个规则加到ParticleState Module里, 这样参数设置错误的时候就可以报警:
[Image Removed]
[Attachment Removed]