Replication can occur on the archetype instead of the right sub-object

What happens:

Given certain conditions even if the Actor instance is fully built, client side the replication of components occurs on archetypes instead of the object instances.

Expected behaviour:

Replication should always occur on the subobject instances instead.

Various thoughts:

We’re not sure on what triggers this behaviour, judging from our project there can be multiple causes since for us restarting the editor isn’t enought to resolve the issue, while it works for Blueprints that have a direct C++ parent.

It seems one of the requisite for it to happen is to have blueprint class that has at least another blueprint as parent.

From our tests, all the subobjects are correctly instanced and initialized both on server and client, simply the replication process takes the wrong object to write to.

Note that the exception (a fatal one) that raises following the repro steps in the given project example could be avoided with a check on the pointers, but that’s not the real issue, the important part is the callstack and what happens before that point.

Let us know if you need more clarifications.

[Attachment Removed]

Steps to Reproduce
1) Open the attached project with UE 5.7.4, in debug mode from Visual Studio

2) The editor should open on TestMap. If not, open Maps/TestMap

3) Click on the 3 dots near the play button, to change PlayMode and Play Settings

4) Set Number Of Players to 2

5) Click to Advanced Settings, and set these releveant options:

Run Under One Process -> true

Play Net Mode -> Play as listen server

6) Press play, move with WASD and get close to the only asset in scene, draw on it holding the left mouse button, note that works on both client and server

7) Stop

8) Go into the asset folder Content/CopyGirls/Environment/StaticBPObjects

9) Click with RMB on BP_StaticEnvironmentActor -> Create Child Blueprint Class, name it BP_Test

10) Open BP_Test, select the StaticMesh component, set a mesh of choice (Like a cabinet door), Compile and Save the blueprint, close it

11) Drag BP_Test in the scene, and place them near the already present BP_StaticEnvironmentActor

12) Press play and try to draw on the newly added BP_Test, an exception will occur.

Now, looking at the callstack, in particular at the fourth element (DBSurfacePaint.dll!FDBFastPaintList::PostReplicatedAdd), you can notice that it’s replicating the state to “BP_PaintableComp_GEN_VARIABLE”, an archetype, instead of the right subobject.

In this example project, this happens with newly created blueprints: if you restart the editor, it will work as intended.

In our project sometimes it happens even after restarting the editor, not sure if there can be multiple causes.

[Attachment Removed]

Since i can’t see the example project, maybe it failed the upload.

I’ll try to reupload it here

[Attachment Removed]

Hi,

Thank you for the report and repro project. After looking into this, it seems like the issue doesn’t lie with replication but rather with how the default property values are being handled for the blueprint class.

After creating the BP class derived from BP_StaticEnvironmentActor and starting PIE, I can observe the constructor for the UDBPaintableComponent is passing in the expected value for the FastPaintList.PaintableComponent.

However, after the constructor is finished, FObjectInitializer::InitProperties changes the pointer to the BP archetype (BP_PaintableComp_GEN_VARIABLE), a value its getting from the DefaultData object. Here’s the callstack from when that happens:

    UnrealEditor-DBSurfacePaint.dll!UE::CoreUObject::Private::Copy<FDBFastPaintList>(void * Dest, const void * Src, int ArrayDim) Line 1378	C++
 	[Inline Frame] UnrealEditor-CoreUObject.dll!UScriptStruct::ICppStructOps::Copy(void *) Line 1981	C++
 	UnrealEditor-CoreUObject.dll!UScriptStruct::CopyScriptStruct(void * InDest, const void * InSrc, int ArrayDim) Line 3707	C++
 	UnrealEditor-CoreUObject.dll!FStructProperty::CopyValuesInternal(void * Dest, const void * Src, int Count) Line 344	C++
 	[Inline Frame] UnrealEditor-CoreUObject.dll!FProperty::CopyCompleteValue(void *) Line 930	C++
 	[Inline Frame] UnrealEditor-CoreUObject.dll!FProperty::CopyCompleteValue_InContainer(void *) Line 936	C++
>	UnrealEditor-CoreUObject.dll!FObjectInitializer::InitProperties(UObject * Obj, UClass * DefaultsClass, UObject * DefaultData, bool bCopyTransientsFromClassDefaults) Line 4560	C++
 	UnrealEditor-CoreUObject.dll!FObjectInitializer::PostConstructInit() Line 4240	C++
 	UnrealEditor-CoreUObject.dll!FObjectInitializer::~FObjectInitializer() Line 4112	C++
 	UnrealEditor-CoreUObject.dll!StaticConstructObject_Internal(const FStaticConstructObjectParameters & Params) Line 4845	C++
 	UnrealEditor-CoreUObject.dll!FDuplicateDataWriter::GetDuplicatedObject(UObject * Object, bool bCreateIfMissing) Line 184	C++
 	UnrealEditor-CoreUObject.dll!FDuplicateDataWriter::operator<<(UObject * & Object) Line 78	C++
 	[External Code]	
 	[Inline Frame] UnrealEditor-Engine.dll!operator<<(FArchive &) Line 4350	C++
 	UnrealEditor-Engine.dll!AActor::Serialize(FArchive & Ar) Line 976	C++
 	UnrealEditor-CoreUObject.dll!StaticDuplicateObjectEx(FObjectDuplicationParameters & Parameters) Line 3066	C++
 	UnrealEditor-Engine.dll!UWorld::GetDuplicatedWorldForPIE(UWorld * InWorld, UPackage * InPIEackage, int PIEInstanceID) Line 4493	C++
 	UnrealEditor-Engine.dll!UWorld::DuplicateWorldForPIE(const FString & PackageName, UWorld * OwningWorld) Line 4565	C++
 	UnrealEditor-Engine.dll!UEngine::LoadMap(FWorldContext & WorldContext, FURL URL, UPendingNetGame * Pending, FString & Error) Line 16365	C++
 	UnrealEditor-Engine.dll!UEngine::TickWorldTravel(FWorldContext & Context, float DeltaSeconds) Line 16037	C++
 	UnrealEditor-UnrealEd.dll!UEditorEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 2157	C++
 	UnrealEditor-UnrealEd.dll!UUnrealEdEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 546	C++
 	UnrealEditor.exe!FEngineLoop::Tick() Line 5977	C++
 	[Inline Frame] UnrealEditor.exe!EngineTick() Line 60	C++
 	UnrealEditor.exe!GuardedMain(const wchar_t * CmdLine) Line 190	C++
 	UnrealEditor.exe!LaunchWindowsStartup(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow, const wchar_t * CmdLine) Line 266	C++
 	UnrealEditor.exe!WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * pCmdLine, int nCmdShow) Line 338	C++
 	[External Code]	

After restarting the editor, the above still happens in InitProperties, but it appears as though the pointer is then later set back to the expected value when the actor component and its properties are serialized from StaticDuplicateObjectEx.

I’m not sure why this is only occurring for BP classes derived from a BP class, as well as why restarting the editor appears to fix the issue. To look into the problem further, I’ve opened a new issue, UE-380307, which should be visible in the public tracker in a day or so.

In the meanwhile, I believe you can try working around the issue by setting the FastPaintList.PaintableComponent pointer back to the correct value after the component’s constructor, such as in the component’s BeginPlay.

Thanks,

Alex

[Attachment Removed]

Hi Alex,

thank you for the quick feedback, your suggested workaround seems to be working!

We will go with that for now.

Thanks you very much,

Gian Paolo

[Attachment Removed]