Download

Best Practice Question; "child" actors.

So I am coming from Unity/UDK.

Apparently the concept of a preset configuration of actors/components in a hierarchy is now one of the several things that share the name “blueprint” (is a Prefab in Unity, and I think it was called artifact in UDK)

However what I cant seem to figure out is what the best practice is for connecting these things together internally.

Lets say I have the following “blueprint”

SomeGuy (UMyActorClass, Blueprint)
∟Child1 (SceneComponent)
∟Child2 (SceneComponent)
[INDENT]∟Grandchild1 (SceneComponent)
∟Grandchild2 (SceneComponent)[/INDENT]

UMyActorClass happens to also have 4 variables



USceneComponent* Child1;
USceneComponent* Child2;
USceneComponent* Grandchild1;
USceneComponent* Grandchild2;


I have seen three ways to approach this
1. Create the children in C++
Basically, in UMyActorClass::BeginPlay(), create the children. This is fine if what your doing happens to allow you to do this. In my case, however, I want artists to be able to tweak those children in relation to eacother in the editor. I could create separate blueprints for each of those children, but obviously thats a pretty heavy handed thing to do and kinda defeats the purpose as artists wont be able to manipulate the whole object at once

2. Manually assign all variables using the ‘blueprint’ GUI
Putting aside feeling like a child connecting boxes with lines, this technically works. However its really clunky (and fragile). More so if Child2 happens to be a class that references its own children. If I have to connect child variables to grandchild boxes in my parent blueprint ill wind up with a spagettii of boxes and lines just to assign variables – making me thing is not the best practice way to do this.

3. “Searching” for children in C++ in UMyActorClass::BeginPlay()
Aside from the fact that there does not seem to be a mature way to do this (everything I have seen involves you literally creating a for loop and iterating over children and checking string names when you assign in the editor, yuck), this technique does not seem to work properly in the editor. The C++ BeginPlay() only seems to be called at runtime, where as the junky blueprint “Event BeginPlay” seems to be able to assign variables that the editor.

Clearly this is such a common thing that I must be missing something conceptually! What am I missing, how is this normally done?

I’m not quite understanding what you are trying to do/what your question is.

If the question is, How can I enforce a certain hierarchy within C++? You can simply overload the PostInitComponents step of your UMyActorClass and do some validation there then reset/fix the data yourself. You can see a diagram of the Actor lifecycle here.

If the question is, How can I set a field in relation to changes made by Designers/Artists during Editing? You can overload the PostEditProperty method in your UMyActorClass which will tell you exactly what field changed (and what the new value is), so you could manually update your shadow copies then.

If the question is, How do I make sure I have certain components on my Actor? You can easily do that with all the various FindComponentByClass/GetComponentsByClass methods in UActor. You shouldn’t need any string name checking or anything like that.

I think what I am asking is so basic that I overstated my question.

Lets say I have a UMyActorClass which has 5x USceneComponent pointers, and I have a “blueprint” of UMyActorClass that has 5x child components. What is the best practice way to map those things together?

I see this as something that will be done basically all the time by everyone, so I cant imagine the answer is that involved.

  • I Assume the best practice is not through blueprints, (maybe thats obvious?)
  • GetComponentsByClass wont really work because they are all the same class
  • Manually naming them in the editor or creating tags THEN calling GetComponentsByClass is pretty clunky

You could just use a double pointer.



UPROPERTY(BlueprintReadWrite)
USceneComponent* MyPublicVariable;

USceneComponent** MyInternalVariable;

// In your Constructor, or PostLoad, or wherever.
{
   MyInternalValue = &MyPublicValue; // No matter what MyPublicValue is set to through the editor, you can always access it through simply dereferencing MyInternalValue (e.g. *MyInternalValue)
}




UPROPERTY(BlueprintReadWrite)
USceneComponent* MyPublicVariable;


What is the best practice way to assign MyPublicVariable in the editor?

Do I have to use blueprints?

Do I have to do something like



	for (UActorComponent* child : GetOwner()->GetComponentsByClass(USceneComponent::StaticClass()))
	{
		if( child->GetName() == "SomeNameHere" )
			MyPublicVariable = Cast<USceneComponent>(child);
	}


You don’t have to use blueprints, you could set it through the properties panel. There’s a bunch of boilerplate code that will be automatically generated for you and handle all the editor interaction for you.

I think you’re overthinking things, create your class and open it in the Editor (place an instance of your Actor) and everything will become MUCH clearer.

Ok, so for people in the future, here my summary of how this works.

The best practice, is to avoid creating your C++ components in blueprints.

In Unity, you create objects in the editor and reference them in your prefab. You can accomplish this in unreal, but its really fragile (something being referenced ‘out of order’ will just flatly hard crash the editor without an understandable error message)

If you want to use something in C++, then create it in C++ in your actors constructor.



	UPROPERTY(EditAnywhere)
	UBoxComponent* Box;




	// Add the box component
	Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Bounding Box"));
	Box->SetupAttachment(RootComponent);
	Box->RegisterComponent();


CreateDefaultSubobject actually does some voodoo to where the component it creates is persistent and editable in the editor. You can even hand-code default values. This functionality is actually pretty cool so I have no idea why its not documented at all. Right now the API documentation for this method is literally “Create a component or subobject”. People just seem to know how it works, and I guess now you do too!

Things I have noticed that are worth making note of. Maybe some of these are incorrect, so hopefully someone will correct me.

  • The first CreateDefaultSubobject you call magically makes itself the RootComponent.
  • I have seen lots of people manually assign the first item they create to RootComponent, however I dont know why since it seems to do it ‘under the hood’
  • components created with CreateDefaultSubobject will append the word ‘(Inhereted)’ to their name in the editor.
  • Calling ‘RegisterComponent’ will allow the component to tick.