OnComponentCreated not called when using CreateDefaultSubobject?

OnComponentCreated is called as part of the Spawn process. In AActor::PostSpawnInitialize we dispatch the OnComponentsCreated call which does the set up, then they get registered.

If you want to manipulate the ChildActor from the owning Actor in code you should look at overriding PostActorCreated.

Hello,

I have an actor which has a native ChildActorComponent, declared in the C++ header like so :

UPROPERTY( Category = Hoop, VisibleAnywhere )
TSubobjectPtr< UChildActorComponent > PlayerStartCompnent;

This component is created in the constructor of the parent class :

AParent::AParent(
    const class FPostConstructInitializeProperties& PCIP
    ) : 
    Super( PCIP )
{
    MeshComponent= PCIP.CreateDefaultSubobject< UStaticMeshComponent >( this, TEXT( "MeshComp" ) );

    RootComponent = MeshComponent;

    PlayerStartCompnent = PCIP.CreateDefaultSubobject< UChildActorComponent >( this, TEXT( "PlayerStartComponent" ) );
    PlayerStartCompnent->ChildActorClass = APlayerStart::StaticClass();
    PlayerStartCompnent->AttachTo( MeshComponent );
}

In the code, I want to access to the ChildActor property of UChildActorComponent. But this value is NULL.

To be initialized, the function UChildActorComponent::OnComponentCreated must be called, which is not the case. I put a breakpoint in this function, and never broke on it.

But the actor seems to be created anyway, because when I update the position of the actor in the editor, I can get the correct value when I call :

ParentActor->PlayerStartCompnent->GetComponentLocation();

I suppose this is a bug, because using Blue prints, it seems that this function gets called.

Or do I have to manually call this function in the PostInitializeComponents function of the parent actor?

Thanks

The problem is that PostSpawnInitialize is called for the various gamestates, bots, controllers, and so on, but it is not called for this actor, which is in fact a BluePrint placed in the world.

The class owns a static mesh and 4 child actor components (all of the same type : APlayerSTart)

I saw in AActor.h that I can use PostActorCreated if the actor is spawned, and POstLoad if the actor is serialized, which I think is my case.

So, should I manually call OnComponentCreated on each of the 4 playerstart in PostLoad, as it doesn’t seem to be called anyway?

I still think this should be automatically called, whether the actor has been spawned or deserialized, don’t you think?

Ok, I believe I see what you’re referring to now. If the ChildActorComponent is a native component and it is placed in the world then you never get the OnComponentCreated call, which is, I agree, bad and a bug.

I’ve entered the bug in our system, I’m not quite sure where the right spot to make sure it gets called from is, but we’ll get it worked out.

Thanks for the report.

I tried to call DispatchOnComponentsCreated in the POstLoad function, and didn’t get any problems

Hello,

do you know if this bug is fixed in the upcoming 4.2 release?

I’m afraid it is not. I am currently working on hardening Child Actor Component but those changes should come in 4.3. I will provide you with a github link to the fix for this specific issue once it is submitted.

OK, Thanks for your reply.

It’s not urgent at all, I’m looking forward for your github link

Hello again Zoubi. The blueprint side of child actor component has been hardened and I was coming back around to this issue and I’m wondering whether in 4.2 the issues you were seeing are still present? While OnComponentCreated is still not called, I don’t think that is a problem any more in 4.2 because the ChildActor pointer is no longer transient.

Let me know if you still think that there is an issue that needs resolving her or not as I’m currently leaning towards a feeling that it is working correctly.

Hello,

sorry for the late reply.

In my code, I used (with the 4.1 release) to add a call to OnComponentCreated in the PostLoad function of my parent actor, in order for the ChildActor pointer to be set.

I’ve commented all this code, with the 4.2 release, and indeed it does work.

So I would say it is fixed for me :slight_smile:

BTW, I compared ChildActorComponent.h between the 4.1 and 4.2 releases, and the only relevant change is the UPROPERTY declaration above ChildActor.

What’s the difference between DuplicateTransient (4.1) et NonPIETransient (4.2)?

Thanks

There are too many kinds of transient :stuck_out_tongue:

Transient: This means that the variable will not be saved, in the case of child actor component this would have meant the actor remained in the world but the reference to it lost.

DuplicateTransient: This means when we duplicate the object (such as we do for PIE), the value is not copied over. This similarly meant that while the Child Actor remained in the Level when we PIE (due to it also being duplicated), the reference to it was lost.

NonPIETransient: This is the opposite of DuplicateTransient. It means it should be transient unless we are duplicating for PIE (this was my first try at the fix, but it only fixed the PIE case and saving for standalone was still broken).

And finally TextExportTransient (which is what it should be in 4.2): Says that when we do a text export (which is what happens when we copy/paste), don’t copy the value. Without this value when we duplicated the ChildActorComponent we ended up with 2 components pointing to the same Actor because the copy paste doesn’t include the ChildActor.

Thanks for your explanations

Hi Marc, I’m wondering if this has been broken again. In 4.5 I’m able to reproduce exactly the kind of behavior that Zoubi is describing - i.e. my ChildActor is null unless I manually call OnComponentCreated. There seem to be quite a few questions on AnswerHub that are pointing to the same thing (see links below where people are attempting to call CreateChildActor manually because their child actor is not being automatically created).

For some background on my usecase - I’m porting some of my Blueprints to C++ and I have a ‘builder’ blueprint actor that generates many child actors dynamically. I was using SpawnActor at first and trying to parent it to my actor (by setting owner/ParentComponentActor/attachactortoactor/etc) but this didn’t seem to work. Fortunately UChildActorComponent does exactly what my Blueprints did once I apply the OnComponentCreated workaround.

Hi ,

That issue seems to be related to a known bug (UE-6932) that started in 4.6.1. We are aware of the issue and a developer has reviewed and prioritized it. I have added a note that this is affecting many users and needs to be fixed as soon as possible. Thank you for your report.

Hello,

is this bug going to be resolved any time soon?

I’m unfortunately experiencing this bug with a builder blueprint I tried to port to C++ as well.

Thanks

Hey Zoubi-

The bug report that mentioned is still being worked on by a developer. I’m unsure of the exact time frame for a fix but this issue is getting attention and should be fixed in a future update to the engine.