Announcement

Collapse
No announcement yet.

Component pointer changes between constructor and OnRegister call

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Component pointer changes between constructor and OnRegister call

    Hello.

    Could anyone help me understand how creation of components work?

    Let's say I have following component. Its purpose is to attach InstancedMeshComponent as child to Actor.

    Code:
    // WallComponent.h
    class ARCHITECTURE_API UWallComponent : public USceneComponent
    {
    // basic stuff
    
    protected:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = TestComp, meta = (AllowPrivateAccess = "true"))
    UInstancedStaticMeshComponent* _instances;
    
    }
    Code:
    // WallComponent.cpp
    
    UWallComponent::UWallComponent() {
    UE_LOG(LogTemp, Warning, TEXT("UWallComponent constructor %s starts"), *name); auto name = this->GetName(); name += FString("-wall"); _instances = CreateDefaultSubobject<UInstancedStaticMeshComponent>(*name); _instances->SetupAttachment(this); _instances->CreationMethod = EComponentCreationMethod::SimpleConstructionScript; auto owner = GetOwner(); if (owner) {
    UE_LOG(LogTemp, Warning, TEXT("UWallComponent (%s): owner exists (%s)"), *this->GetName(), *owner->GetName()); UE_LOG(LogTemp, Warning, TEXT("UWallComponent (%s): _instances: (%s)"), *this->GetName(), *_instances->GetName()); // name is Wall-wall
    }
    } void UWallComponent::OnRegister() {
    Super::OnRegister(); if (_instances) {
    UE_LOG(LogTemp, Warning, TEXT("UWallComponent (%s): OnRegister _instances: %s"), *GetName(), *_instances->GetName()); // name is WallComponent_0-wall
    }
    }
    And Logs:

    Code:
    LogTemp: Warning: UWallComponent constructor Default__WallComponent starts
    LogTemp: Warning: UWallComponent constructor WallComponent_0 starts
    LogTemp: Warning: UWallComponent constructor Wall starts
    LogTemp: Warning: UWallComponent (Wall): owner exists (TEST_ACTOR_BP_C_0)
    LogTemp: Warning: UWallComponent (Wall): _instances: (Wall-wall)
    LogTemp: Warning: UWallComponent (Wall): OnRegister _instances: WallComponent_0-wall
    In logs I see:
    1. Constructor was called 3 times (might have something with CDO? But why not 2 times?)
    2. Value of _instances is changing between function calls:
    - in constructor was to _instances pointing to component with name Wall-wall (as I would expect)
    - inside function OnRegister is _instances pointing again to WallComponent_0-wall (also in other functions, so acessing _instances properties becames impossible)

    Is there simple explanation for this behaviour? I could not find any resources explaing components lifecycle in depth.

    #2
    Components cannot safely own (or be the Outer for) other Components, Compoents can only be owned by Actors. A lot of things will break if you don't adhere to that rule. It definitely won't work creating them in a constructor. You also won't see them in the details panel, despite marking them with Edit/Visible Anywhere.

    At best, you can override your "container" components' OnRegister() function and and create additional components using it's owning Actor as the outer through NewObject<>();

    Comment


      #3
      Originally posted by TheJamsh View Post
      Components cannot safely own (or be the Outer for) other Components, Compoents can only be owned by Actors. A lot of things will break if you don't adhere to that rule. It definitely won't work creating them in a constructor. You also won't see them in the details panel, despite marking them with Edit/Visible Anywhere.

      At best, you can override your "container" components' OnRegister() function and and create additional components using it's owning Actor as the outer through NewObject<>();
      Thanks, TheJamsh that helped.

      This is how my code looks now:
      Code:
      void UWallComponent::OnRegister()
      {
      Super::OnRegister(); auto name = this->GetName(); name += FString("-wall"); _instances = NewObject<UInstancedStaticMeshComponent>(GetOwner(), *name); _instances->RegisterComponent(); _instances->AttachToComponent(this, FAttachmentTransformRules::KeepRelativeTransform); _instances->CreationMethod = EComponentCreationMethod::Instance; GetOwner()->AddInstanceComponent(_instances);
      }
      Now I can access _instances property using BP or C++. Big step forward.
      But in ClassDefaults in Blueprint editor I still see value as None.

      Do I understand correctly that there is nothing I can do about it?

      Comment

      Working...
      X