Correct way to have custom SceneComponents that contain other SceneComponents

I’ve sided heavily away from using Actors and have started using components almost exclusively, but I keep running into issues with this approach and hot reload.

Errors like this:

“failed to resolve archetype object - property values may be lost.”

“Ensure condition failed: GIsTransacting”

Error: Component has X in its AttachChildren array, however, believes it is attached to Y

And I’m frequently unable to save maps after hot reload because of:
Graph is linked to private object(s) in an external package.

I don’t think I’m doing anything crazy here, but wondered if anyone had any tips on how to get this to work. (For example, do I need to override RegisterComponent in my custom component and call RegisterComponent on child components?).

Here’s some code I’m using to make a gear stick :



Class USlideLever;

UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class MYGAME_API UGearBox : public UStaticMeshComponent, public ILeverFeedbackInterface
{
    GENERATED_BODY()

public:
    // Sets default values for this component's properties
    UGearBox(const FObjectInitializer& ObjectInitializer);
    virtual void SetLeverValue(float value) override;
    virtual void SetLeverActive(bool isActive)override { LeverActive = isActive; }

protected:
    UPROPERTY(VisibleAnywhere)
        USlideLever* GearStick;


And the Constructor cpp:



UGearBox::UGearBox(const FObjectInitializer& ObjectInitializer) :Super(ObjectInitializer)
{
    GearStick = CreateDefaultSubobject<USlideLever>(TEXT("GearStick"));
    GearStick->SetupAttachment(this);

    PrimaryComponentTick.bCanEverTick = false;
}


Doesn’t seem too crazy a thing to do, but hot reload pretty consistently breaks these components (even if you’re not working on that cpp file or even any element of the blueprint that throws the errors).

Any ideas?

I think it might have something to do with the fact I set the object name to a static value (as in above: TEXT(“GearStick”)). It can mean I have multiple objects in an actor with the same named component.

I’ve tried using MakeUniqueObjectName(this, GetClass(), TEXT(“GearStick”));

But this ends up creating GearStick_1 in the blueprint and GearStick_2 in the spawned component in game. The saved blueprint values don’t reference GearStick_2 so it’s NULL at runtime.

Hi,

I have the exact same problem you described in this post. Have you managed to solve it? The solution you described here with MakeUniqueObjectName allowed you to get rid of the problem permanently?

Any help would be really appreciated cause I’m getting sick of these errors.

Thanks!

I’m not an expert just started learning few weeks ago, I do read engine code a lot every day to boost my knowledge, I might be wrong but your constructor seems to be bad.



 UGearBox::UGearBox(const FObjectInitializer& ObjectInitializer) :Super(ObjectInitializer)
{  
  GearStick = CreateDefaultSubobject<USlideLever>(TEXT("GearStick"));
    GearStick->SetupAttachment(this);
     PrimaryComponentTick.bCanEverTick = false;
} 

This is user code obviously and it looks like it attaches a component to it self, but whether the UGearBox object is considered valid at this point is what I don’t know for sure so here is how it goes.
You said you don’t use actors so much but just components, you should think of Actors as containers of components therefore know that components on it’s own means nothing.
Every Actor class has a root component member which is by default is nullptr.
In order to start adding componets to your actor (that is component container) you should assign exaclty one component to RootComponent pointer. that one component should inherit from
USceneComponent or you could create dummy USceneComponent and attach it to your actor to become root:

for example:


ExampleActorConstructor()
{
          USceneComponent* MyRoot = CreateDefaultSubobject<USceneComponent>("MyRoot");
          this->RootComponent = MyRoot; // this-> not needed of course, but denote that RootComponent is member of Actor!

          // now start adding your components to MyRoot as you wish
          UStaticMeshComponent* mesh = CreateDefaultSubobject<UStaticMeshComponent>("MyMesh");
          mesh->SetupAttachment(MyRoot);
          // and so on...
}

Know that anything you place into a world is an Actor or inherits from an Actor, I think you can’t place component into the level, that sounds odd because as I said Actors are containers and components are Actor members, that is what actor consists of (that’s how all this actor/componets stuff seems to be designed)

Hope that helps to some extent.

EDIT:
I just now figured out this thread is 2years old rofl :smiley:
Never mind hopefully **PaRaNo0 **learns something here.