How to "expose on spawn" a constructor param in C++?

In BP you can “expose on spawn” a variable and you will have an option to feed some value in it on “SpawnActorFromClass” node.

In vanilla C++ you just define a constructor with params.

How do yo make it in UE4’s UCLASS C++?

You create the variable as a UPROPERTY and also give it a special parameter. Here is an example:

UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (ExposeOnSpawn = true), Category = "MyClass")
	int Foo;
3 Likes

You have to use SpawnActorDeferred. This answer should be still valid.

2 Likes

Thanks, but this is a solution for exposing on BP, while i need to feed that in C++ spawn. sorry for confusing you :stuck_out_tongue:

your answer might be useful for future viewers though.

1 Like

It seems like a messy workaround, isn’t there a better and straighter way for achieving that?

Your question wasn’t entirely clear on that. Last I checked there is no way to do the equivalent when spawning an actor in C++.

What you can do is use a static variable as temporary storage. Set it before you spawn an instance of the class, then in the constructor/whatever you can get the value and clear it. As long as you’re only doing this in a single thread, it will be fine.

Other than that, I think Ninjin’s answer is the best you’re going to get.

Messy? It’s 3 lines of code. Spawn, Init, FinishSpawn. You need a 2nd function to call when creating the actor anyway, since the CDO is already created and you can’t just re-run the constructor. You can put the code for FinishSpawn in your Init function, but I would stick to the 3 line combo.

1 Like

it’s messy because it breaks the function-programming paradigm of 1task=1function and therefore will cause forgotten 2 lines big time.

BP has an option to expose on spawn, it seems very strange to me that it’s not available in C++ spawns. why would i need a 2nd/3rd function to call when crating the actor?

Logically it is completely possible to add inputs, for example adding an override for SpawnActorFromClass(), that has the input params you need, which just calls the other “classic” overrides and then runs the init+finishSpawn.

It seems too strange to not be implemented by Epic in the first place, that’s what caused me asking if there’s some more straight-forward way i am not aware of

Logically it is completely possible to add inputs, for example adding an override for SpawnActorFromClass()

Well, you answered your own question. It is impossible to add overrides for every object you wish to have the expose on spawn functionallity. To do something like the BP implementation on C++, it would need to dynamically alter the SpawnActorFromClass() function depending on the class you are spawning. Since this is not possible without the reflection code that makes Blueprints so helpful in these sorts of scenarios, you can use SpawnActorDeferred.

SpawnActorDeferred is a very helpful and really not messy way to do things. It gives you greater control over everything as you actually get a pointer to the object without running the constructor.

1 Like

Did you see that I mention the word CDO (which stands for Class Default Object, here my own 5 sec google search)? Because if you did and searched what it means and why it’s being used, it should be understandable why you can’t re-run the constructor. There is other functions that get called right after the constructor to initialize some stuff that is needed for the editor and the whole reflection system. One of these hidden functions also creates Blueprints. So, in that sense, if you call a “Blueprint Constructor”, you call one of these post functions and not the C++ Constructor. Therefore, to get the same behavior in C++, you should implement a function that is exactly doing this. You might be able to find the function that is called in Blueprints, but last time I checked you shouldn’t use it, because it comes with boilerplate code for Blueprints and if you make a Blueprint and change your Construction Script (which if you notice is not even called Constructor on purpose) things get even worse.

1 Like

you don’t need to specify args for each existing type. C++ templates come in handy for that. I know UE4 doesn’t support templates anywhere, but there are exceptions and Epic’s workarounds which we might not be aware of.

for example there is a type for wildcard inputs.

I know what’s CDO and how classes in UE4 are being instanced for quite a while now.

The point is that i didn’t ever say i want to run the constructor, rather i want to spawn an object with input similar to BP “expose on spawn” or C++ constructors params.

I am not sure why you mention that, perhaps we have confused each other :stuck_out_tongue:

You dont.

You spawn an actor, then set the values to what you want. Spawning from the Blueprint does this. Nothing written code does not do this. However you make a single line of code look it is still executing 1 instruction at a time, however many dozens, hundreds, thousands, or millions of instructions are invoked. They are still only executed 1 instruction at a time.

I’m not sure where you got this “1task=1function” idea, but you might as well unlearn that right now. Your entire application is running from a single function called main(). EVERYTASK = 1 function.

1 Like

OK guys this is getting ridiculous. At this point you’re not trying to get to an answer anymore. I’m turning off notifications. But before I do I will once again suggest the very easy (but not elegant way) to do what you want. Here is a sample class that does it. It will work fine as long as you are using the main thread – and since that’s the only place you can spawn from, this will always work as long as that doesn’t change.

H:

UCLASS()
class SHOOTER_API AMyActor : public AActor
{
	GENERATED_BODY()

public:
	AMyActor(const FObjectInitializer& ObjectInitializer);

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int MyVar1;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool MyVar2;

	static AMyActor* Spawn(UWorld* world, int myVar1, bool myVar2);

private:
	static bool ParamsSet;
	static int Param_Var1;
	static bool Param_Var2;
};

CPP:

int AMyActor::Param_Var1 = -1;
bool AMyActor::Param_Var2 = false;
bool AMyActor::ParamsSet = false;

AMyActor::AMyActor(const FObjectInitializer& ObjectInitializer)
	:	AActor(ObjectInitializer)
{
	if(!ParamsSet)
	{
		UE_LOG(LogTemp, Error, TEXT("AMyActor spawned without using internal Spawn function!"));
	}
	else
	{
		MyVar1 = AMyActor::Param_Var1;
		MyVar2 = AMyActor::Param_Var2;
	}
}

AMyActor* AMyActor::Spawn(UWorld* world, int myVar1, bool myVar2)
{
	AMyActor::Param_Var1 = myVar1;
	AMyActor::Param_Var2 = myVar2;
	AMyActor::ParamsSet = true;

	AMyActor* myActor = world->SpawnActor<AMyActor>(); 	// fill Spawn() with parameters as you need

	AMyActor::ParamsSet = false;

	return myActor;
}

Obviously you don’t need to make the members as UPROPERTY, I just wanted to be explicit about what was what.

It’s a paradigm from functional programming. If you have 2 functions that you always or mostly execute one after another, it’s a good habit to combine them into one function (possibly 3rd), without this paradigm, we would still write in assembly language.

Whole the point of functions is to encapsulate smaller steps into a shortcuts.

I am not going to unlearn that.

Anyway, your answer have helped me and it’s not your fault for something being subjectively “messy” for me, so i am marking your answer, thanks :]

You are asking to change C++ constructor params without running the constructor and the only way to do this, is running a function after your constructor, which you can define yourself. Luckily, Blueprints already have such a function and the ExposeOnSpawn was neatly integrated with this function = ConstructionScript.
You got a valid question why Epic didn’t refactor this function into 1 line of code where you specify the functionname in the parameter list of SpawnActorDeferred and if I had to guess, they don’t bother and think people use these kinds of features in BPs anyway or they didn’t want to implement a function in AActor called ConstructionRound2 that only calls FinishSpawn and needs to be overridden. Probably not that easy, something is probably missing. But then again, I don’t want to know how exactly Actors are spawned, when they locate memory and what else is happening when Spawning. Maybe there is something magical I miss, but I doubt you will find such an answer here on Answerhub. It’s okay to ask though, there is always this slight chance an engine programmer has a happy day :).

… Check this as well … : ) ,
https://answers.unrealengine.com/questions/292074/spawn-actor-with-expose-on-spawn-variables-in-c.html