How to make a blueprint derived from a UObject class access World

I have a C++ class deriving from UObject which I am then using as my base class for some blueprints.

As UObject does not know how to access World, all the methods that require a WorldContextObject (e.g. GetGameMode) cannot be used.

I know how to get world in my class and have implemented GetWorld. However, this does not appear to be sufficent for the blueprint editor to allow me to create WorldContextObject-dependant functions. What else do I need to do to tell the blueprint graph to use the world supplied by GetWorld()?

In Blueprint you can use the world context from there.

try something like this to hide WorldContext

UFUNCTION(BlueprintPure, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
void Examplefuntion(UObject* WorldContextObject);

Or try this

UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", CallableWithoutWorldContext))
void Example2(UObject* WorldContextObject);

Just curious, how do you get the World ?

I don’t know how to do that. Working with UE, I’ve learned that trying to force functionality, usually means a bad approach.
Maybe you can make them Actors or avoid calling functions that need world context here

I know where I am creating the objects (they always have a specific ActorComponent as their outer so I can just call GetWorld on their outer. (e.g. GetOuter()->GetWorld()).

Thanks for the answer but this isn’t quite what I wanted. I want to be able to call existing functions like GetGameMode which require the blueprint to have a WorldContextObject. They work in blueprints derived from UActorComponent for example, but they can’t be added to my blueprints. This would just allow me to make new functions that I’d be able to call.

This is possible. The short (simplified) answer is all you have to do is override GetWorld() to get the methods to show up. Hooray!

The reason why that wasn’t working for me (and probably a bunch of other people) is, if your implementation of GetWorld() called another objects GetWorld, for example:

// We know this object is always attached to an ActorComponent which does implement GetWorld
return GetOuter()->GetWorld();

This would cause it to fail.

#The problem
Skip to the fix if you are not interested

For the functions to show up in the BP editor, UObject::ImplementsGetWorld() must return true. This function works by calling GetWorld and seeing if a variable called bGetWorldOverridden (which it sets to true) is set back to false by the default implementation of GetWorld. That’s fine - you’ve overridden GetWorld so it shouldn’t right?

Unfortunately, the ImplementsGetWorld is called on the CDO (the class default object), whose outer isn’t something sensible like the ActorComponent you always attach your object. This new outer doesn’t implement GetWorld so bGetWorldOverriden (a global variable) gets set back to false, meaning the method doesn’t show up in the blueprint editor.

#The fix
An incredibly ugly fix you can do to force this to work is as follows:

if (GetOuter()->IsA(UActorComponent::StaticClass()))
{
	return GetOuter()->GetWorld();
}
else
{
	return nullptr;
}

Here, we check if the outer is something sensible (in my case, I know it is an ActorComponent, so I can check the outer is indeed an ActorComponent. If it is, we are a normal object so we can call my correct GetWorld implementation on the Outer.

If the outer is not an ActorComponent then (I’m assuming) we are the CDO and we are being tested to see if we actually implement GetWorld(). It doesn’t matter than we return null, the key thing is we don’t call UObject::GetWorld so the editor thinks we have implemented GetWorld. It therefore shows the methods.

1 Like

Nice explanation!.
But rather than checking your outer, you can check if the current object is CDO or not. this is done by checking
!HasAnyFlags(RF_ClassDefaultObject))
This worked for me.

1 Like