GetWorld() returns NULL in ActorComponent startup callbacks

There is a pattern that recurs multiple times in our codebase: a component type registers itself with a singleton manager actor once at the time it spawns (for example, a “TargetableComponent” calls the game state to add itself to a dynamic array of “targetable actors”).

Ideally this would be a simple call inside the “OnActivate” or “OnRegistered” callbacks in the component class. However, these don’t work for actors that are hand-placed in the level, because GetWorld() returns NULL at the time that the callbacks are invoked.

Right now we have a horrible hacky work-around: we set up the component to generate ticks, register the component with the singleton within the TickComponent method, and then turn off ticks forever. This is ugly.

It is notable that BeginPlay on the actor does the right thing at the actor level – GetWorld() always seems to return the non-NULL, whether for hand-placed actors or actors spawned by code or blueprint later. So an actor that needs to register with a singleton can do so in a single codepath inside of BeginPlay.

Is there another Component callback I should be implementing other than OnActivate or OnRegistered that behaves properly? Or do I need to continue in my filthy work-around?

bump 4.21.2

Does your singleton rely on a valid World instance? Is it static or do you have a static accessor? Can you decouple the reliance on the World from your singleton?

Have you tried another area of the UObject/AActor lifecycle? Perhaps PostSpawnInitialize, maybe?