World context object

I found out that all you need to do is override GetWorld() but you have to take care not to call GetWorld() on the outer object in the CDO, which may be the transient package or something else that doesn’t implement GetWorld().

The engine calls UObject::ImplementsGetWorld() on your Class Default Object (CDO) in several places to show/hide and enable/disable certain pins as well as determine their default values. The implementation of UObject::ImplementsGetWorld() basically just sets a global boolean to true and UObject::GetWorld() sets it to false. So you have to take care of the following:

  • Don’t call Super::GetWorld() unless you’re sure your base class implements GetWorld() properly
  • Don’t call GetWorld() on anything else that may not override it.

Here’s what I ended up with:

UCLASS(BlueprintType, Blueprintable)
class WHATEVER_API UWhateverObject : public UObject
{
    GENERATED_BODY()
    UWorld* GetWorld() const override
    {
        if (IsTemplate() || !GetOuter()) // We're the CDO or have no outer (?!).
        {
            return nullptr;
        }
        return GetOuter()->GetWorld();
    }
};

As @dzarafata already mentioned, most of your custom UObject derivatives are likely to have an outer that has a connection to a world, e.g. a UActorComponent or AActor, so this implementation should work out well for most use cases.

3 Likes