Can you use a Blueprint Function Library in an Object Class

You can actually call it if you also override UObject::ImplementsGetWorld() (note that the method is guarded with #if WITH_EDITOR).

I’ll wrap the information out a bit as it’s all scattered across multiple posts and it’s a bit hard to follow right now:

UObjects have a safety mechanism that disallows you from using any function that uses a WorldContextObject internally, as it’s possible that the world is invalid in a UObject and that would cause a crash.

However, you may know what you’re doing and may be perfectly safe to do so.

In that case, you must override the UObject::GetWorld function. But be careful! Because depending on how you override it, you may still have the same problem.

The default UObject::GetWorld() sets a flag that identifies that method as the default method. So if you override GetWorld() with Super::GetWorld() you’re gonna have the same problem, because that flag will still be set. Same if you override it with GetOuter()->GetWorld() as that’s gonna use the default GetWorld() implementation of the outer object. Even if you expect your object’s outer to be an actor, the default object (which is the one you’ll be modifying in blueprint) won’t have that outer.

Then, there’s this other virtual method, UObject::ImplementsGetWorld():

#if WITH_EDITOR
bool UObject::ImplementsGetWorld() const
{
	bGetWorldOverridden = true;
	GetWorld();
	return bGetWorldOverridden;
}
#endif // #if WITH_EDITOR

So as you can see, it’s going to assume the GetWorld is overridden and then actually call the implementation. As the default method sets bGetWorldOverriden = false, ImplementsGetWorld will return false as the world hasn’t been overridden.

If you really have to, you can always override UObject::ImplementsGetWorld() to always return true. This way, you can still return the outer’s world & use static methods that require the WorldContextObject.

My suggestion though is implementing the method like this (based on the Actor’s implementation):

UWorld* UMyCustomObject::GetWorld() const
{
	// CDO objects do not have a world.
    // If the object outer is destroyed or unreachable we are likely shutting down and the world should be nullptr.

	if (UObject* Outer = GetOuter())
	{
		if (!HasAnyFlags(RF_ClassDefaultObject)
			&& !Outer->HasAnyFlags(RF_BeginDestroyed)
			&& !Outer->IsUnreachable())
		{
			return Outer->GetWorld();
		}
	}

	return nullptr;
}

This way we make sure that the default object doesn’t get in the way and we can still have the outer’s GetWorld() implementation (as if it’s an Actor, for example, the default implementation won’t set bGetWorldOverriden = false). As you can see it all depends a bit of your problem’s context.

Of course, this safety mechanism is there for a reason. Make sure that the world you’re returning exists and it’s consistent if you’re going to call these functions or otherwise you’ll be having a crashy engine.

For blueprint-only users though, I don’t think there’s a way around this. If all of this sounds way too advanced, maybe you can have your class inherit from AInfo instead which is a special kind of Actor that doesn’t have a physical representation. This way you can still modify the blueprint but you don’t have this limitation of uobjects, as actors are spawned into a world, unlike uobjects. That class is thought more for manager classes though, but maybe it works for you.

5 Likes