groom在UE5.7出了dataflow的功能,我希望用这个功能让动画驱动groom
但是我发现,只有在我做成一个蓝图预设的时候,dataflow才能生效。而动态创建component再修改Mesh deformer,模拟就失效了。
是不是动态挂载的方式还需要调用一些其他的初始化接口?
我还遇到很迷惑的现象,在附件工程里好像出不来,但是在我自己的工程里,我只要双击打开groom asset,或者场景里摆放一个蓝图拼好的dataflow角色,有概率突然就能成功模拟了,但是下次启动引擎就又失效了。这里是不是有cache相关的操作?
[Attachment Removed]
奇怪。附件没上传成功吗,我再传一次。
重现步骤:
打开附件工程的DataflowBug关卡
可以看到关卡里有两个蓝图,一个是内容实例里的Aera角色,他有Dataflow模拟的头发,头发能正常绕到肩膀另一头。
第二个蓝图BP_DynamicAera是我用动态创建Component的方式拼装的Aera,他的Dataflow模拟失效了。
[Attachment Removed]
RoryXY
(Xiao Yue)
3
您好,
我发现附件工程里两处设置有些问题:
- groom是绑定到在马尾辫子骨骼上的, 动画来源是Hair_Deform_AnimBP中的Rigid Body模拟, 但BP_DynamicAera中并没有把这个马尾骨骼加进来, 应该是下图的这个SetSkeletalMeshAsset节点填错了, 需改成Hair_L_DutchBraid_Tri.
- 动画驱动的groom目前需要设置AttachmentName, 将他attach到父级skeletal mesh的正确骨骼上.
[Image Removed]
修改过后, 我这边看辫子的动画表现是正常的. [Image Removed]
[Attachment Removed]
非常感谢,确实是这样,原来AttachmentName需要设置。顺便还有一个刚刚发现的问题,左边这个蓝图拼好的角色,如果我把他Attach到随便一个东西上,他的dataflow也不动了,这个是不是个bug。 [Image Removed]
[Attachment Removed]
RoryXY
(Xiao Yue)
5
这应该是个bug. 原因是在groom的mesh deformer里, 查找骨骼动画来源的Skeletal Mesh的逻辑是GetAttachmentRootActor, 也就是从attach到的根Actor上找. 具体参考DeformerGroomInterfaceUtils.h中的GetGroupSkelMesh.
我觉得这里改成先在Owner Actor中查找, 再到Root Actor上查找更合理一些, 可以同时覆盖蓝图封装以及groom独立挂在角色Actor上的情况, 如下, 测试可以修复.
后面我再问下开发怎么修复合适, 有更新和你沟通, 感谢反馈!
FORCEINLINE USkeletalMeshComponent* GetGroupSkelMesh(const UGroomComponent* GroomComponent, const int32 GroupIndex, int32& MeshLOD)
{
if (GroomComponent)
{
auto FindInActor = [&](AActor* Actor) -> USkeletalMeshComponent*
{
if (!Actor) { return nullptr; }
TArray<UActorComponent*> ActorComponents;
Actor->GetComponents(USkeletalMeshComponent::StaticClass(), ActorComponents);
for (UActorComponent* ActorComponent : ActorComponents)
{
if (USkeletalMeshComponent* SkeletalMeshComponent = Cast<USkeletalMeshComponent>(ActorComponent))
{
if (GroomComponent->GroomAsset && (SkeletalMeshComponent->GetSkeletalMeshAsset() ==
GroomComponent->GroomAsset->GetDataflowSettings().GetSkeletalMesh(GroupIndex)))
{
MeshLOD = GroomComponent->GroomAsset->GetDataflowSettings().GetMeshLOD(GroupIndex);
return SkeletalMeshComponent;
}
}
}
return nullptr;
};
AActor* OwnerActor = GroomComponent->GetOwner();
if (USkeletalMeshComponent* Found = FindInActor(OwnerActor))
{
return Found;
}
AActor* RootActor = GroomComponent->GetAttachmentRootActor();
if (RootActor != OwnerActor)
{
if (USkeletalMeshComponent* Found = FindInActor(RootActor))
{
return Found;
}
}
}
MeshLOD = INDEX_NONE;
return nullptr;
}
[Attachment Removed]