Accessing Blueprint / ChildActorComponent properties from Python

`add_light_params = unreal.AddNewSubobjectParams(
parent_handle=scene_handle,
new_class=unreal.ChildActorComponent,
blueprint_context=bp_asset,
)

subobj_data_subsys.rename_subobject(handle=subobj_handle, new_name=actor.get_name())
subobj_data_subsys.attach_subobject(owner_handle=scene_handle, child_to_add_handle=subobj_handle)
child_actor_comp = unreal.SubobjectDataBlueprintFunctionLibrary.get_object(unreal.SubobjectDataBlueprintFunctionLibrary.get_data(subobj_handle))
child_actor_comp.set_child_actor_class(actor.get_class())
child_actor_comp.set_world_transform(actor.get_actor_transform(), False, False)`

Steps to Reproduce
I’m using the Unreal Editor Python API to automate the creation of some components in an existing blueprint, based on what’s found in a user’s scene/level. This is working well for turning static mesh actors in a level into StaticMeshComponents in the target BP. Now I’m attempting the same with Blueprint Actors used for lighting. These lighting BPs are placed in the level and often customized per-instance, with modified light colors, attenuation, etc. Those property overrides need to be replicated in the target BP as well. This is working up to a point…

First I’m turning them into ChildActorComponents in the target BP, as shown below. After that runs, the desired lighting BP shows up as expected in the target BP when loaded in the blueprint editor. The property overrides applied in the “source” level do not. This isn’t surprising since all I’m doing is referencing that BP’s class in the ChildActorComponent. I thought the solution may be to set the “child_actor” property on the component to be the one from the level. Something like this:

child_actor_comp.set_editor_property(‘child_actor’, actor)

However, that editor property is read-only. I’ve found no way to set the actual child actor, or otherwise bring the overrides over into the target BP this is building.

Is what I’m attempting possible/correct, but just a limit of the current Python API exposure? Or is there a better approach for this?

Thank you.

`add_light_params = unreal.AddNewSubobjectParams(
parent_handle=scene_handle,
new_class=unreal.ChildActorComponent,
blueprint_context=bp_asset,
)

subobj_data_subsys.rename_subobject(handle=subobj_handle, new_name=actor.get_name())
subobj_data_subsys.attach_subobject(owner_handle=scene_handle, child_to_add_handle=subobj_handle)
child_actor_comp = unreal.SubobjectDataBlueprintFunctionLibrary.get_object(unreal.SubobjectDataBlueprintFunctionLibrary.get_data(subobj_handle))
child_actor_comp.set_child_actor_class(actor.get_class())
child_actor_comp.set_world_transform(actor.get_actor_transform(), False, False)`

Hi Adam,

Sorry about the delay. I’m looking into this and should get back to you soon.

Best regards,

Vitor

Hi Adam,

The Child Actor Component controls the lifetime of the Child Actor: it spawns the child actor when it is registered and destroys it when unregistered. This is why you cannot change the “Child Actor” property directly. On the other hand, once you set the “Child Actor Class”, the component creates an internal actor called “Child Actor Template”, which is used to initialize the actual child actor once it is spawned. You should be able to change properties on that template to achieve what you need, but you will need to use C++ to implement and expose to Python some helper functions:

`UCLASS()
class UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()

public:

UFUNCTION(BlueprintPure)
static AActor* GetChildActorTemplate(UChildActorComponent* ChildActorComponent)
{
return ChildActorComponent->GetSpawnableChildActorTemplate();
}

UFUNCTION(BlueprintPure)
static UActorComponent* GetComponentByClass(AActor* Actor, TSubclassOf ComponentClass)
{
return Actor->GetComponentByClass(ComponentClass);
}

};`With this in place, you can something like the following in Python:

`child_actor_component.set_child_actor_class(unreal.PointLight)

child_actor_template = unreal.MyBlueprintFunctionLibrary.get_child_actor_template(child_actor_component)
child_actor_template = unreal.PointLight.cast(child_actor_template)

point_light_component = unreal.MyBlueprintFunctionLibrary.get_component_by_class(child_actor_template, unreal.PointLightComponent)
point_light_component = unreal.PointLightComponent.cast(point_light_component)

point_light_component.set_light_color(unreal.LinearColor(1,0,0,1))`Note that you might run into some difficulties along the way because of how the Child Actor Component works (configuring a non-spawned template actor, then spawning and despawning the actual actor when registered and unregistered, which happens more often than you’d think). For example, when testing the solution I just presented, I had initially used “point_light_component = child_actor_template.get_component_by_class(unreal.PointLightComponent)”, but for some reason I could not get this to work, and was able to work around it by creating my own wrapper GetComponentByClass() function in C++.

As for alternative solutions, it could be helpful to learn more about the reason behind what you are trying to achieve, but in any case here are some thoughts:

- Follow your first approach whenever possible, for example by creating PointLightComponents in the target actor directly to replace PointLightActors

- Simply attach your “child blueprint” to the target blueprint, instead of using a child actor component, if this is enough for your needs

- Use instanced levels: maybe you could keep the user scene/level untouched and use a Level Instance Actor to instantiate it inside another level, if that resonates with your end goal

Please let me know if this is helpful and if you have any further questions.

Best regards,

Vitor