this is some problem. I try to spawn actor from BP class object but it doesn’t work. It gave me error “Pin World context object must have conection” but it doesn’t has this pin. Is that bug? Where I can get this pin, or that I need do? I am searching on forums but it gave me nothing… Any ideas? Sorry for terrible english.
objects do not exist in a world, so they cannot spawn actors, unless you give them a context actor, so the spawn function knows what world you are talking about. in C++, context actors are required to GetWorld(), but this option may be missing from blueprint, so spawning actors from objects is not recommended.
you might have several worlds at once. for example, in an arena combat game, one player may be watching a killcam replay in a separate world than another player who is in battle. if you wanted, you could spawn actors into the replay world, without spawning them into the combat world, but you would need to pass an actor from the replay world into the context input of the spawn function, or call the spawn function from within an actor that exists in the replay world.
so basically, you should only spawn actors from other actors.
if you want to spawn an item actor from an item object, you should probably keep an array of those objects in an Actor called Inventory. this InventoryActor can get data from its objects and spawn actors into the world, although you could also do that with structs instead of objects, and it would cause less memory overhead.
Thanks. I think it was all what I want to know.
You can create UObject base class in C++ with:
UCLASS(BlueprintType, Blueprintable, Abstract, Meta = (ShowWorldContextPin))
class YOURGAME_API UObjectWithWorldContext : public UObject
and then make your BP Objects children of it
Meta = (ShowWorldContextPin)
will make all, normally hidden, WorldContext pins visible, and You can provide an object with WorldContext Yourself, being able to use any functions from inside Classes derivated from this class.
Otherwise the WorldContext pin is hidden and You cannot connect anything to it, even if Your object has reference WorldContext, or has a field that has one (e.g. it has an Actor reference that You set during construct/ or in some custom init function)
When creating an object You have to provide the “Outer” object. If this outer has access to the world (You used actor/ actor component / object that already had world context), then You can just connect self when calling those functions as Your object actualy already has oaccess to the world (GetWorld function returns Outer->GetWorld(), if the object don’t have the world set, so it will work just fine if at least the outer object has the world reference).
TBH, probably 99% of objects You usually create by Yourself will have reference to the world anyway, but blueprints won’t let You even let You try by default because of some edge case where You created an object using a game instance as the outer or something like that
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 implementsGetWorld()
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.