Passing arguments to constructors in UE4?

As I understand it, UE4 constructors in 4.6.1 contain a single argument, passed by address, of type FObjectInitializer. This argument may not be used to store a custom-made argument list for initializing the object that is being created. Furthermore, the three functions that are normally used to create UE4 objects, namely NewObject, NewNamedObject and ConstructObject, do not provide a means of passing arguments to the object being created. This makes it impossible, apparently, to thoroughly initialize a given object within the object’s constructor itself. One way to initialize the object would be to write an initialization method that was called after ConstructObject() returned the object, but this sort of initialization would introduce numerous inconveniences of its own, as you would need to include checks in other methods just to see if it had been called yet.

It seems as though there is no way to elegantly initialize objects in UE4. Am I missing something, though? Is there in fact a way to pass your own arguments to constructors, or at least pass initialization functions and argument lists to some function like ConstructObject?

1 Like

Take a look at:

  • PreInitalizeComponents - Called before components of the actor are initialized
  • PostInitalizeComponents - Called after every Component is initialized
  • PostInitProperties - Called after Blueprint Properties are initialized

Use UProperties for variables of the object and default initialize them either in the constructor or in one of those methods.You can write your own Spawn Method that passes in parameters using:

UGameplayStatics::BeginSpawningActorFromClass(...)
// .... set your properties here
UGameplayStatics::FinishSpawningActor(...)

I hope this gives you a good starting point.

[EDIT]

There is no variadic template magic for the ConstructObject functions as far as i know. So the most pragmatic way would be to write your own ConstructObject wrappers for the Objects you need

UMyObject* ConstructMyObject(int32 myIntParam, FString myStringParam, 
          UObject* Outer = (UObject*)GetTransientPackage())
{
  auto Obj = ConstructObject<UMyObject>(UMyObject::StaticClass(), Outer);
  Obj.setInt(myIntParam)
  Obj.setStringParam(myStringParam);
  return Obj;
}

So a little bit of boilerplate work for each type but it should be doable.

[/EDIT]

Have a nice Day!

Thanks for the reply; your suggestions would not solve my particular problem but do provide insights. The issue is that all the classes I have written so far are subclassing from UObject, not AActor, and so I can’t overload UWorld::SpawnActor as a way to “inject” parameters into objects. I’ll have a careful look through the API and see whether UObject has any other methods I could call.

Just overworked my answer, this should work for you if you add the guideline to use your Construct function wrappers everywhere instead the ones provided by the Unreal-Engine or do I miss a requirement?

Hey, did you find way to do this nicely?

Hey, here’s one way round I use to construct and init my UObjects in one call.
In one sentence: make a static function that takes in the desired parameters, creates the UObject, inits it with the params and returns it at the end.

For example, I have this UWeapon that extends UObject and I want to create a big list of them to add to the inventory, I can do so with:

Inventory.insert(UWeapon::MAKE(EWeaponType::HSword, "BlameGT", FWeaponDmg(20)));
Inventory.insert(UWeapon::MAKE(EWeaponType::HSword, "Pity", FWeaponDmg(20)));
Inventory.insert(UWeapon::MAKE(EWeaponType::Sword, "Hemorragy", FWeaponDmg(20)));
Inventory.insert(UWeapon::MAKE(EWeaponType::Sword, "StraightKatana", FWeaponDmg(20)));

Instead of:

UWeapon * weapon = NewObject<UWeapon>();
weapon.init(...params...);
Inventory.add(weapon);

In my Weapon.h I define:

static UWeapon* MAKE(EWeaponType wepType, FString name, FWeaponDmg wepDmg);

In Weapon.cpp i implement:

   UWeapon* UWeapon::MAKE(EWeaponType wepType, FString name, FWeaponDmg wepDmg){
        UWeapon* w = NewObject<UWeapon>();// UWeapon();
        w->init(wepType, name, wepDmg);
        return w;
}

Hope it helped :wink:

4 Likes

Wow, thanks man!

This has bothered me to no end, and your solution is only reasonable one i have seen so far.

Does anybody know if there is some more elegant way to do this in newer unreal versions? or is this still the way to go?

1 Like

Really spend too much time on this issue already! Apparently, for as far as i could find, we still need to use the method described here.

What you are looking for is called a static factory method. Or a abstract factory.

So you have some method or class responsible for correctly initializing your object and only returns it when it is in a vailid state.

Attached a design pattern card

Does anybody know if there is some more elegant way to do this in newer unreal versions? or is this still the way to go?

Nope this is the most elegant way.