4.6 Get Outer of UObject c++

Hi.

I’m trying to understand the actor-component mechanisms in UE4 and few things are still unclear to me, can I count on Your help?

I have an APawn called AHero. AHero has UPROPERTY UBag* Bag, where UBag is an UObject. The Bag is set up as an subobject in AHero constructor:

Bag = PCIP.CreateOptionalDefaultSubobject<UBag>(this, TEXT("HerosBag"));

The UBag has also a function that needs an access to the game instance MYGameInstance : UGameInstance.

Because UBag is an UObject it doesn’t have an access to the World (thereby to the GameInstance), so I’m trying to get it’s parent - an AHero:

AHero* Hero = Cast<AHero>(GetOuter());

But for some reason, the received AHero is pointing to the Class Default Object (CDO) which hasn’t access to the World!

I was trying to give an UBag a pointer: AHero* Parent and assign it in the AHero constructor:

Bag->Parent = this;

But the Parent is still pointing to the CDO…

The problem can be solved by changing the UBag from UObject to an UActorComponent but I’m curious about few things:

  1. Why when I’m using UObject the Outer is an CDO?
  2. What is a purpose of CDO anyway? I was reading a documentation, but it’s still unclear to me why every object has to have an instance even when they are not created?
  3. I found a tip about using ConstructorHelpers::CreateComponent on https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/Classes/index.html#componentsandsub-objects but I can’t find this function in the Engine. Is the documentation outdated?

You are using the wrong place to set of the parenting, if you use the FObjectInitializer ctor you are doing it in the default object itself. The FObjectInitializer ctor is there to handle any default value initialization, for example creating your subobject. So what I propose is once you create your actor set the parenting either in PostBegin or in PostInitializeComponents. The first one is called only in gameplay code right after your actor has entered the game logic while the later is called just after all components of the actors has been initialized.

Thanks for a response!

That tip about PostBegin and PostInitializeComponents is great, I’ll be able to fix few other things with that, thanks :slight_smile:

So the CDO is some kind of default object which is used to create other instances? And the constructor is working only for this default object itself? When I was debugging the code the constructor was running also when the Hero was spawned into the world…

And why UActorComponent worked? GetOuter gave me the proper Actor there, not CDO (it also has an access to the World!).

I’m still pretty confused. Manually setting the parent is rather a workaround. There should be a way to get an instance of the Actor from subobject which this Actor has. Right?

Yes there is a way, once I have access to my PC I’ll post a sample ^^

Just to add a bit more info. It works with components because they are the children of an actor and handled specially, they maintain an hirachy. If you just use UObject they will not maintain such a special relationship between each other.

Actor on the other hand do maintain a similar relationship by setting the base of an actor using SetOwner, the child actor can then request the owner by calling GetOwner.

But GetOuter should work in the PostBegin or PostInitializeComponents methods I think.

Ok, I tried few things having your answers in mind and there are few conclusions:

  1. To add a component to an actor better not use the pure UObject, because there will be no proper relationship between them. GetOuter in UObject will always point to the parent’s CDO.
  2. When adding component, which is a specialized one, the component can use GetOuter to get it’s parent.
  3. We can create hierarchy of Actors using SetOwner and GetOwner (but it works only for Actors!)
  4. When using FObjectInitializer ctor initialize only default objects. Do not create new ones, do not make assign etc. because making CDO will screw around. Do this in PostBegin or PostInitializeComponents (or if it is pure UObject, better make some kind of Init function).

Is everything correct?

I was used to the situation that in c++ programmer has control when the constructor is run. In UE4 some stuff is happening automatically, which can be confusing…

The UObject hasn’t got PostBegin and PostInitializeComponents. Actors have, but in Actors GetOuter is working like it should :wink:

That sums it all up basically. If you use any thing that inherits from UObject you are forced to use the engines framework, this is due to the reflection system between C++ and BluePrints (behind the scenes it is actually a binding between C++ and UnrealScript byte code, BPs compile to that byte code) and of course the GC and memory handling.

Ok, it is clearer for me now. I still have no idea what’s the purpose of the CDO and how it actually works, but managing objects and actors is easier for me now.

Thanls :slight_smile:

Oh, by the way, we found another good workaround :slight_smile:

In Actor’s PostInitializeComponents we can simply create UObject’s instance with this as an Outer.

Bag = NewObject<UBag>(this);