Download

Structs, how to initialize one as a variable?

I have a struct that I am using, and all is well, except for the fact that I can’t seem to initialize my struct. I am trying to do:


FMyStruct TestStruct(Params)

, but am getting an error saying that there is no default constructor. I am also getting no hint as to which parameters my struct needs. I want to see a hint like this:
7af8fcda85b1f3b8dedd8c549f91d5b50209bdce.png

Here is how I declare my struct:


USTRUCT(Blueprintable)
struct FMyStruct
{
	GENERATED_USTRUCT_BODY()
		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Struct")
			 FName MotherNanny;
		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Struct")
			FName KeyRing;
		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Struct")
			float Scones;
};

The exact thing I am trying to do is:


MyArrayOfStructs.Add(FMyStruct("Nanny's Mother", "Keyed Car", 2))

What am I missing?



USTRUCT(Blueprintable)
struct FMyStruct
{
	GENERATED_BODY()

	// default constructor -- without parameters, so it will work inside other structures 
	// that need default initializer, such as TArray
	FMyStruct()
	: MotherNanny(TEXT("")), KeyRing(TEXT("")), Scones(-1.f)
	{}

	// constructor that takes 3 parameters
	FMyStryct(const FName& InMotherNanny, const FName& InKeyRing, float InScones)
	: MotherNanny(InMotherNanny), KeyRing(InKeyRing), Scones(InScones)
	{}

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Struct")
	FName MotherNanny;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Struct")
	FName KeyRing;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Struct")
	float Scones;
};


Thanks! So from what I understand, a struct constructor is like the name implies, a constructor that runs when the struct constructed, and sets the struct’s variables based on what was passed to the constructor.

Yepp that’s true…

I think that macro GENERATED_BODY() for structs provides default constructor (while GENERATED_USTRUCT_BODY() does not). So that would have been enough to overcome compilation error.

However, you also need constructor with 3 parameters for your initialization while adding to TArray.

There are few more tricks you can do to your Struct to get them even more TArray-friendly.

Below is one of the structs we have in our game; note that we don’t explicitly add default constructor, “GENERATED_BODY()” does that for us, based on assignment in declaration, eg DamageMax = 0;

At the end, we overload “less than”, and “is equal” operators, to allow TArray.Sort() and TArray.Find(). In our case, effect (buff or debuff) is considered identical if it came from the same ParentAbility (spell) is the same effect index (when spells have more than one effect), came from the same instigator, and has the same name. We consider effect “smaller” than other effect, if time remaining is smaller.



USTRUCT(BlueprintType)
struct FAbilityEffect
{
	GENERATED_BODY()

	// Effect Type
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		EAbilityEffectType Type;

	// Minimum damage, if applicable
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		int32 DamageMin = 0;

	// Maximum damage, if applicable
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		int32 DamageMax = 0;

	// Area affected in cm, if applicable
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		float AreaRadius = 0.f;

	// Flag whether damage gets added to current weapon's damage
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		bool AddToWeapon = false;

	// Duration in seconds
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		float Duration = 0.f;

	// Stat Modifier (for Buffs and Debuffs)
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		EStatModifier StatModifier;

	// Modification amount absolute (negative for debuffs, positive for buffs)
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		float ModifierAmount = 0.f;

	// Modification amount percentage/fraction (1.0 is no change, 0.7 for 30% debuff, 1.3 for 30% buff)
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		float ModifierPercentage = 1.f;

	// Leap Inpulse
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AbilityEffect)
		float LeapImpulse = 0;

	// particle effect while under the influence
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = VisualEffects)
		UParticleSystem* EffectParticle = NULL;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = VisualEffects)
		TSubclassOf<AActor> EffectReplacementActorClass = NULL;

	// grounnd hit decal, on the ground of the hit (eg at the feet or enemy)
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = VisualEffects)
		TSubclassOf<class ADecalActor> GroundDecalClass;

	// flag to enable right leg trails
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Properties)
		bool RightLegTrails = false;

	// flag to enable left leg trails
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Properties)
		bool LeftLegTrails = false;

	// animation montage while effect active
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Properties)
		UAnimMontage* Animation = NULL;

	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		UParticleSystemComponent* EffectParticleComponent = NULL;
	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		AActor* EffectReplacementActor = NULL;
	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		FString Name;
	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		ATraverseBaseCharacter* Instigator = NULL;
	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		int32 Index = 0;
	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		float fRemainingTime = 0.f;
	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		int32 iRemainingTime = 0;
	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		float RemainingModifierAmount = 0.f;

	UPROPERTY(BlueprintReadOnly, Category = RuntimeParams)
		UAbility* ParentAbility = nullptr;

	// support for TArray.Sort() -- we sort on float time remaining
	FORCEINLINE bool operator<(const FAbilityEffect& V) const
	{
		return fRemainingTime < V.fRemainingTime;
	}

	// support for TArray.Find()
	FORCEINLINE bool operator==(const FAbilityEffect& Other) const
	{
		if (Index != Other.Index) return false;
		if (ParentAbility != Other.ParentAbility) return false;
		if (Instigator != Other.Instigator) return false;
		if (Name != Other.Name) return false;
		return true;
	}

};


1 Like

That’s pretty cool! I am using my setup in a plugin, and receive errors when just using GENERATED_BODY(), or it might be because I’m working in 4.6 lol.