TObjectPtr casting with const correctness in 5.4 and Gameplay Abilities

Hello there!

In 5.4 release there is a peculiar line in release notes.

  • Cast, ExactCast and CastChecked with TObjectPtr are const correct

Meaning if it’s a pointer to a const object it will not allow casting to pointer to non-const, which was allowed prior 5.4.

For some time I’m actively using Gameplay Abilities and particulary activation with Gameplay Event. This way I have access to GameplayEventData where I can pass some references to optional objects for more complex manipulations without need to reach outside of ability to look up required objects.

The trick is in declaration of FGameplayEventData.

	/** The instigator of the event */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = GameplayAbilityTriggerPayload)
	TObjectPtr<const AActor> Instigator;

	/** The target of the event */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = GameplayAbilityTriggerPayload)
	TObjectPtr<const AActor> Target;

	/** An optional ability-specific object to be passed though the event */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = GameplayAbilityTriggerPayload)
	TObjectPtr<const UObject> OptionalObject;

	/** A second optional ability-specific object to be passed though the event */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = GameplayAbilityTriggerPayload)
	TObjectPtr<const UObject> OptionalObject2;

All pointers are pointers to const objects, preventing me from calling any non-const functions when casting to required type.
Before 5.4 it wasn’t a problem it just casted into pointer to non-const without problem.
Since blueprints aren’t really about consts, they also ignore it all and make casts to modifiable non-const objects if I were to make Gameplay Ability logic using blueprint.
Also if I were to just force through with const_cast it also works just like before.

But now I’m confused about what is a supposed approach? Is GameplayEventData not meant to let you modify these objects and I must do it some other way? Am I supposed to make it in blueprints? Is it all just a collateral damage?

Or am I just approaching gameplay abilities wrong?

I’m not doing anything too serious, just passing into ability a ref to instance of equipped firearm, so ability could get some data and tell gun to lose some ammo from the mag if it’s a success.

I’m running into this same problem and found myself in this thread. My only thought is that Target is expected to be some custom actor type that we populate ourselves with actual targeting data (i.e. a custom Actor class that contains a non-const pointer to the actor I want to affect). That seems a little needlessly “extra” for the sake of const correctness – I have an actor I want to target, so I want to just populate Target with my actor. In the meantime, I’m going to perform a const_cast<...>() to get rid of the const-ness and hope it doesn’t cause trouble.