Is it possible to use editor value in class constuctor

Hello. Im not sure the title of the question is even 80% accurate.

Anyway I want to spawn an array of “child actor components” (no problem there ( for now ) ) depending on the size of a UProperty i have set up. But when i tried that ofc, it defaults to 0 ( as that is default ) at first. But even, if I change it in the editor it stays 0, throughout the construction and on my begin play" breakpoints - it has been changed to the value given from the editor.

So is it possible through ‘some means’ to be able dynamically change a exposed to editor property and for it to effect constructor or should i just do the components creation in the “begin play”

Well, a constructor (as i’m sure you know :D) simply represents the ‘layout’ or floor plan of the class and when it becomes an object the variables are the defaults when constructed.

So if I understand your question correctly then I would say no it is not possible. After the initial construction of course it is possible to edit the values but otherwise if you want the default values to be something else then place it in the constructor.

If you want to change it at run time rather then creation then you’ve got the right idea. Use BeginPlay.

Yes, it’s possible using the OnConstruction function. Basically, this is called each time you modify a property in the editor. So, if you want to have 2 actor component after you input 2 in the editor, Spawn those components in the OnConstruction call.

You can do it in Blueprint or C++.

The C++ function signature you need to overide is this :

#if WITH_EDITOR
	virtual void OnConstruction(const FTransform& Transform) override;
#endif

I recommend using the #if WITH_EDITOR macro here just so its explicit this is only true in the editor.

After that, you can spawn components. Here is an example:

for (int32 i = 0; i < nNbComponentsToSpawn; i++)
{
	USphereComponent* spawnPoint = NewObject<USphereComponent>(this);
	spawnPoint->CreationMethod = EComponentCreationMethod::UserConstructionScript;
	spawnPoint->AttachParent = RootComponent;
	spawnPoint->bCastDynamicShadow = false;
	spawnPoint->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
RegisterAllComponents();

In this scenario, nNbComponentsToSpawn is the variable you have change value of, and it’s going to spawn the right number of components (sphereComponents in this case).

I think this is what you wanted?

Hope this helps,

Mick

Thank you very much :slight_smile: this helps a lot. I can’t wait to go and try it.

a small issue arose - since NewObject - ‘NewObject’ : invalid template argument for ‘T’, type expected. And im using - static ConstructorHelpers::FObjectFinder SegmentBlueprint(…) it doesn’t register it at comple-time it seems. Is there a way to ‘circumvent’ this

You cannot use ConstructorHelpers outside of constructors. Can you copy-paste what you are trying to do?

Well I just did everything after begin play. The other thing was just quaility of life thing for later resigns. This is the code in the ‘constructor’

static
ConstructorHelpers::FObjectFinder
SegmentBlueprint( TEXT(
“Blueprint’/Game/Blueprints/TSwitchesPuzzle/LO_Switch.LO_Switch’”
) ); if ( SegmentBlueprint.Object !=
NULL ) { BlueprintTemplate =
(UClass*)SegmentBlueprint.Object->GeneratedClass;
}

in the header is: private: TSubclassOf BlueprintTemplate;
and then

//#if WITH_EDITOR //void
ATSwitchesPuzzle::OnConstruction(const
FTransform& Transform)

I tried another 3-4 spawn methods but none worked, here is what i have leftover in comments

// for( int i = 0; i < PuzzleDimention
; i++ ) // { // // FSwitch
new_switch; // new_switch.id = i;
// new_switch.active = false; //
// new_switch.actor =
SpawnOb( this );
// new_switch.actor->CreationMethod =
EComponentCreationMethod::UserConstructionScript;
// new_switch.actor->AttachParent =
RootComponent;
// new_switch.actor->SetActorEnableCollision(
ECollisionEnabled::NoCollision );
// // //new_switch.SwitchActor =
NewObject( this
,TEXT( “PlateComponent”) ); OLD
// //new_switch.SwitchActor =
ConstructObject(
APipeSegmentC::StaticClass(),
GetOwner(), NAME_None, RF_Transient);
OLD // // // IF ITS CHILD ACTOR CLASS
// new_switch.SwitchActor =
CreateDefaultSubobject(
( FString::Printf( TEXT( “WORKDAMMIT_%u”) , i ) ) );
// // new_switch.SwitchActor->SetChildActorClass(
BlueprintTemplate ); // missing
documentation (dull) // // // // if(
new_switch.SwitchActor ) // // {
// new_switch.SwitchActor->OnComponentCreated(
);
// new_switch.SwitchActor->RegisterComponent(
); // FOR DYNAMIC COMPONETNS ;/
// new_switch.SwitchActor->SetRelativeLocation(
FVector( 100.0f
i , 0.0f , 0.0f ) );
// new_switch.SwitchActor->AttachTo(
RootComponent );

Im sorry for the late response ( few irl stuff got in my way ). This is in the constructor:

static ConstructorHelpers::FObjectFinder<UBlueprint> SegmentBlueprint( TEXT( "Blueprint'/Game/Blueprints/TSwitchesPuzzle/LO_Switch.LO_Switch'" ) );
    	if ( SegmentBlueprint.Object != NULL ) 
    		BlueprintTemplate = (UClass*)SegmentBlueprint.Object->GeneratedClass;	

BlueprintTemplate  is kept in header as  - TSubclassOf<ATSwitchActor>
Then on construct i wanted something like this (few variations were left as commented - none worked ) 

for( int i = 0; i < PuzzleDimention ; i++ )
{

	FSwitch new_switch;
	new_switch.id = i;
	new_switch.active = false;
	
	new_switch.actor = SpawnOb<BlueprintTemplate>( this );
	new_switch.actor->CreationMethod = EComponentCreationMethod::UserConstructionScript;
	new_switch.actor->AttachParent = RootComponent;
	new_switch.actor->SetActorEnableCollision( ECollisionEnabled::NoCollision );
		
	//new_switch.SwitchActor = NewObject<UChildActorComponent>( this ,TEXT( "PlateComponent") ); OLD
	//new_switch.SwitchActor = ConstructObject<APipeSegmentC>( APipeSegmentC::StaticClass(), GetOwner(), NAME_None, RF_Transient); OLD

	// IF ITS CHILD ACTOR CLASS
	//	new_switch.SwitchActor = CreateDefaultSubobject<UChildActorComponent>( *( FString::Printf( TEXT( "WORKDAMMIT_%u") , i ) ) );
	//	new_switch.SwitchActor->SetChildActorClass( BlueprintTemplate ); // missing documentation (dull)


	//	if( new_switch.SwitchActor )
	//	{
	//		new_switch.SwitchActor->OnComponentCreated( );
	//		//new_switch.SwitchActor->RegisterComponent( ); // FOR DYNAMIC COMPONETNS ;/
	//		new_switch.SwitchActor->SetRelativeLocation( FVector( 100.0f*i , 0.0f , 0.0f ) );
	//		new_switch.SwitchActor->AttachTo( RootComponent );

	//	}
	//}
}

RegisterAllComponents( );
Super::OnConstruction( Transform );

I guess Im missing something basic from how the whole spawning/creating components and actor works from my U-knowledge.