How to expose a member variables UPROPERTIES and edit in a blueprint of owning class

Hi guys,

I am implementing a Pickup Item in my current project and have stumbled across something I would really love to do but cannot figure out how to do. It is a very hard question to phrase so I will try to give a code snippet and some context.

I currently have an extremely basic Pickup Item class. For simplicity, I am removing everything that is not relevant to the issue, so it will not be my full class.

UCLASS()
class AWeaponPickup : public AActor, public IInteractable
{
	GENERATED_BODY()

public:

private: 

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Pickup Properties, meta = (AllowPrivateAccess = true))|
class UWeaponData* weaponData_;
}

As you can see, I have a class that holds all the current weapon parameters as a member variable of my Pickup class. I have this class so I can transfer that data when I am picking up / dropping things from an inventory. Below is a subset of items I have in the weapon data class.

UCLASS(Blueprintable)
class UWeaponData : public UBaseData
{
	GENERATED_BODY()

public:

	UWeaponData();

	// Ammo in one magazine
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Data | Weapon")
	int ammoPerMagazine_;

	// Current ammo in the magazine
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Data | Weapon")
	int ammoCurrentMagazine_;

	// Initial ammo in the magazine
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Data | Weapon")
	int ammoInitialMagazine_;
}

My goal is to expose the UPROPERTIES of that Weapon Data class INLINE in my editor, without having to make another blueprint. The below screenshot is what I get out of my Weapon Pickup class, which forces me to create another blueprint of the Weapon Data, and that seems unnecessary.

image

Below here is what I would like to see IN the WEAPON PICKUP blueprint.

I am trying really hard to minimize the blueprint overload when I really only care about the initial values of this weapon and want to be able to tweak them from weapon to weapon. After the game has started, the persistent weapon data should stay in sync.

It seems like a lot of UE components allow for this, I.E, how you can set the skeletal mesh of a skeletal mesh component. It seems like this only works when the component is instantiated and “attached” in the constructor but I cannot attach my UObject class which makes me think I simply cant get this functionality.

You do have a few options but they all have their tradeoffs.

First off, you could use a structure instead of a UObject. This would make it easy to copy that data from the weapon on pickup and to configure it from the weapon blueprint. The downside is that copying that structure could become a problem due to size/properties that it stores.

Next option would be that you could use the Instanced object functionality to do what you want, it would allow you to have a UObject*, you’d select a type (from the subtypes of whatever type the property was) and you’d be able to modify the data. The problem here is that you can’t just copy the pointer to that object around because it’s owned by the blueprint and if it’s ever unloaded you lose your object. So for safety you’d have to copy it anyway, but there are at least some functions you can use to do that.

Structurally I think you have a common problem which is mixing config time & runtime data. On the one hand you have values like magazine size, rate of fire and all the effects and on the other you have things like ‘current magazine’ and ‘currently full auto’. The first type of data is stuff you’d only want to set from the editor and you would want to be consistent across all instances of a certain type of weapon pickup (all AK-47’s or all Peacemakers), while the other is the data specific to one gun (this AK-47 vs that AK-47).

Typically, you’d have a class derived from UDataAsset that you configure with all the config stuff. Then the runtime stuff could be a simple structure that is easy to copy between the places you want to track it. You would either pair with (or include in) the structure a pointer to your data asset. The asset with all the config stuff would then be independent of the blueprint and stay loaded as long as you have the type of weapon, even if the pickup actor goes away.

@MagForceSeven

I appreciate you taking the time for the detailed response - it was super helpful seeing a few different perspectives/options. I was being my head in the keyboard last night trying to find THE solution and I think I got a little tunnel visioned.

I think the feedback for runtime vs config data is probably a large driving factor in me being in the situation I am in. I think I am going to take one step back and explore making the config data in a class derived from UDataAsset and then my runtime data just simple structs, as you suggested. That seems like a streamlined way that I can nail down right now, then run that paradigm through all of my other pickup items (outside of just Weapon Pickups).

You’re welcome. Also remember that you never have to get things right the first time. It’s tempting to try and write code that will never have to be updated but that’s a trap that will just prevent you from getting anything done. Always shoot for ‘a solution’ over ‘the solution’ because you can always change it later based on the things that you learn about the game that you’re making.

Good luck!