BeginPlay() called multiple times on same actor instance

Hello!

I’ve observed that an actor instance can have BeginPlay() called multiple times when it gets streamed out and then in again rapidly. I can reproduce this in a plain UE 5.7.4 project, reproduction steps provided below.

Looking at the code, this seems like this might be intentional - but I cannot find any documentation that indicates it’s an expected lifecycle that an actor that has had EndPlay() called on it can then subsequently have BeginPlay() called on it again (e.g. https://dev.epicgames.com/documentation/unreal\-engine/unreal\-engine\-actor\-lifecycle?lang\=en\-US makes no mention of it).

I’d like to ask then if it is genuinely the expectation that gameplay code must be able to handle BeginPlay() being called on an actor that has already had EndPlay() called? Or is this a bug? If it is expected, please could this be added to the documentation?

Thank you,

Woody

Steps to reproduce:

  • Unreal 5.7.4
  • New blank C++ project
  • Add a C++ actor, StreamingBeginPlayRepro

// StreamingBeginPlayRepro.h

#pragma once

include “GameFramework/Actor.h”

include “StreamingBeginPlayRepro.generated.h”

UCLASS()

class AStreamingBeginPlayRepro : public AActor

{

GENERATED_BODY()

protected:

int32 BeginPlayCount = 0;

virtual void BeginPlay() override

{

Super::BeginPlay();

\+\+BeginPlayCount;

UE\_LOG(LogTemp, Warning, TEXT("\[REPRO] BeginPlay this\=%p name\=%s count\=%d (expected 1 on a freshly constructed instance)"), this, \*GetName(), BeginPlayCount);

}

virtual void EndPlay(const EEndPlayReason::Type Reason) override

{

UE\_LOG(LogTemp, Warning, TEXT("\[REPRO] EndPlay  this\=%p name\=%s reason\=%s"), this, \*GetName(), \*UEnum::GetValueAsString(Reason));

Super::EndPlay(Reason);

}

};

  • Create a new “Open World” level
  • To make the test not take too long, modify the World Settings > World Partition Setup > Runtime Settings > Runtime Partitions > 0 > Main Partition > Cell Size to 3200 and Loading Range to 6400
  • Place an instance of the StreamingBeginPlayRepro actor near the player start actor.
  • Start PIE, and observe the output log whilst flying away from and towards the starting position.
  • Note that BeginPlay() is called multiple times on the same instance of the StreamingBeginPlayRepro actor. The address is identical and BeginPlayCount grows.

[Attachment Removed]

Actually I’ve just spotted that the flow chart on the lifecycle page does have an arrow from UninitializeComponents showing that an actor can be reused, but this is the only indication I can find.

[Attachment Removed]

I have confirmed with an Epic developer through offline channels that this behaviour is intentional.

[Attachment Removed]

It was nice to talk to you on-site! Indeed this multiple BeginPlay is a major gotcha to many folks.

The arrow in the Actor Lifecycle chart, I added relatively recently (two years ago). I’ll raise the topic internally to see if we can come up with better ways to surface.

[Attachment Removed]