TArray with "Instanced" UPROPERTY flag problem

Hey, I’m creating a system for fire modes for a weapon. I want to be able to create and edit the array of fire modes for the weapon in the Blueprint defaults section. Which means the UPROPERTY would be something like this UPROPERTY(Instanced, EditDefaultsOnly, Category=FireMode).
The fire mode is a UClass right now, I’m not sure if that’s necessary or what’s the best way for that. The fire mode does have inheritance and a few methods.
So with that in mind, I tried (note I’m using ~ instead of < and > because they don’t work with Markdown):

  1. TArray~UFireMode*~ Can’t edit the values of the array.
  2. TArray~TSubclassOf~UFireMode~~ I can edit the values here but it’s just a type so I can’t use them later on (as a UFireMode for example).
  3. TArray~TSubobjectPtr~UFireMode~~ This crashes on startup because the subobject isn’t initialized.
  4. TArray~UFireMode~ Of course doesn’t work because it’s a class and the compiler throws an error for not being a pointer.

Should I just use a struct instead? Or am I missing something? The Instanced documentation page doesn’t give a lot of information.

I suggest using the second method you tried. What do you mean can’t use them later on? If push comes to shove, I suggest take an enum approach.

The point is, I want an actual instance, not a type. If I use TSubclassOf I only get the type, right?

Yes it would only be the type. I suggest having two arrays, one with the types which you expose and another which you actually fill up with instances of the object (your first 1).

That’s not what I want though. Maybe I explained it badly.
In UDK there was this FireMode array which you could fill up in the defaults with actual items. So when you started the game they were already instanced and filled with the data you set in the defaults. That’s what I want to do.

TSubclassOf::GetDefaultObject() will return the class default object (that is, the immutable prototype from which objects of that particular class are constructed). That’s all you need, if all you want is to see the default values in the class. If you actually want to instantiate one, you can use ::ConstructObject(), passing the TSubclassOf as the class.

I haven’t tried the instanced tag so I do not know what it does, but I think you will have to do some more legwork here than in UDK. I understand your explanation but without knowing what you are trying to do with the instances I cannot give proper advice. I still recommend the two arrays approach, and in the begin play of the weapon you take the types in the Type array which you have exposed and modified which firetypes are allowed then instance those types and store them in the second array using spawn.

This :), Although if you are trying to get the values in a tick or multiple times I do suggest Instantiating and saving the construct object reference for performance.

Edit: I actually looked through the API because I was curious, the engine saves the default object the first time you call it so successive calls shouldn’t be an issue so GetDefaultObject should be fine.

I didn’t know you’d get the modified values when you construct an object from a TSubclassOf. That does it.

EDIT: This actually doesn’t work 100%. GetDefaultObject on one of the array items of the DefaultFireModes array will return the object with the correct modified property values whereas instancing an object like shown below will return it to the default class property values.

So, the solution it seems:

// In the Weapon's .h file.
UPROPERTY(Instanced, EditDefaultsOnly, Category=FireMode)
TArray<TSubclassOf<UFireMode>> DefaultFireModes;

TArray<UFireMode*> FireModes;

// Then in the .cpp file I iterate through the DefaultFireModes and (simplified)  
FireModes[i] = ConstructObject<class UFireMode>(DefaultFireModes[i]);

So this way I can edit the FireModes in the weapon’s Blueprint directly without having to create extra classes/Blueprints I directly link to just for minor adjustments.

Actually, not really. The default object has the modified properties but if I instance it like this:

UFireMode* FireMode = ConstructObject<class UFireMode>(FireModeSubclassFromTheArray);

it has the default values defined in the FireMode’s constructor.
I tried providing FireModeSubclassFromTheArray->GetDefaultObject() as the Template in ConstructObject, too, to no avail.