I have an actor to which I add replicated components in the OnConstruction function. The components are added on construction because their socket locations can be specified in the actor’s defaults and their number is not fixed. Since moving over to 4.7, using these replicated components causes a crash on remote clients when their parent actor is removed from play. The crash happens in DataChannel::CleanUp in DataChannel.cpp line 1443.
I encountered this issue in a larger project but managed to reproduce it in a minimal C++ project. In this project I spawn a replicated actor, dynamically add replicated components and despawn the actor after 2 seconds. In single player it works, but when a remote client is present it crashes. Please download it here: www.zkshao.com/downloads/RepSubobjectTest.zip
To reproduce the crash:
Generate VS files from .uproject
Compile the source and start the editor
Run TestLevel with 2 clients or dedicated server + 1 client. The crash occurs as long as there is at least one remote client.
Can someone tell me if this is a bug or if I’m doing using replicated components incorrectly? Just to note, this did work in 4.6.
Hey Rama, thanks for replying! The log file doesn’t seem to mention anything about the crash. Here is the call stack on the moment of crashing:
> UE4Editor-Engine.dll!UActorChannel::CleanUp(const bool bForDestroy) Line 1443 C++
UE4Editor-Engine.dll!UChannel::ReceivedSequencedBunch(FInBunch & Bunch) Line 279 C++
UE4Editor-Engine.dll!UChannel::ReceivedNextBunch(FInBunch & Bunch, bool & bOutSkipAck) Line 588 C++
UE4Editor-Engine.dll!UChannel::ReceivedRawBunch(FInBunch & Bunch, bool & bOutSkipAck) Line 344 C++
UE4Editor-Engine.dll!UNetConnection::ReceivedPacket(FBitReader & Reader) Line 979 C++
UE4Editor-Engine.dll!UNetConnection::ReceivedRawPacket(void * InData, int Count) Line 457 C++
UE4Editor-OnlineSubsystemUtils.dll!UIpNetDriver::TickDispatch(float DeltaTime) Line 174 C++
UE4Editor-Engine.dll!TBaseUObjectMethodDelegateInstance<0,UNetDriver,void __cdecl(float)>::ExecuteIfSafe(float <Params_0>) Line 772 C++
UE4Editor-Engine.dll!TBaseMulticastDelegate<void,float>::Broadcast(float <Params_0>) Line 1030 C++
UE4Editor-Engine.dll!UWorld::Tick(ELevelTick TickType, float DeltaSeconds) Line 1027 C++
UE4Editor-UnrealEd.dll!UEditorEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 1329 C++
UE4Editor-UnrealEd.dll!UUnrealEdEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 347 C++
UE4Editor.exe!FEngineLoop::Tick() Line 2257 C++
UE4Editor.exe!GuardedMain(const wchar_t * CmdLine, HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, int nCmdShow) Line 142 C++
UE4Editor.exe!WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow) Line 191 C++
I noticed that sometimes the parent actor removal succeeds without any issues, but most of the time it causes a remote client crash.
ARepActor::ARepActor()
{
bReplicates = true;
}
void ARepActor::BeginPlay()
{
Super::BeginPlay();
if (HasAuthority() && DisplayMesh)
{
// Dynamically spawn some replicated subobjects
for (int i = 0; i < 3; ++i)
{
UStaticMeshComponent * RepMesh = NewObject<UStaticMeshComponent>(this);
RepMesh->SetIsReplicated(true);
RepMesh->SetRelativeLocation(FVector(0, 0, (i + 1) * 200));
RepMesh->AttachTo(GetRootComponent());
RepMesh->RegisterComponent();
RepMesh->SetStaticMesh(DisplayMesh);
}
// Start a timer to destroy self after 2 seconds
FTimerHandle DestroyHandle;
GetWorldTimerManager().SetTimer(DestroyHandle, this, &ARepActor::DestroyMe, 2.f, false);
}
}
void ARepActor::DestroyMe()
{
Destroy();
}
It’s just an actor that adds replicated components at BeginPlay and destroys itself after 2 seconds. The cleanup of the replicated components causes remote clients to crash with high probability.