RemoveAll from TArray with GameplayTag

Hi,

I’m trying to filter out actors from my TArray based on their GameplayTag.
Actors don’t implement the GameplayTag interface on their own so I’m casting them to my BaseGameplayTagActor which just adds this feature to an Actor. My classes derive from this to be able to use GameplayTags.

Right now my setup is the following:

GetOverlappingActors(*outOverlappingActors);

if (outOverlappingActors->Num() < 0)
	return false;

// Predicate creation to allow TArray.RemoveAll
struct IsNotBrickable
{
	bool operator()(AActor *RemovalCandidate) const
	{
		ABaseGameplayTagActor *TagActor = dynamic_cast<ABaseGameplayTagActor *>(RemovalCandidate);

		return TagActor->HasMatchingGameplayTag(itemTag);
	}
};
outOverlappingActors->RemoveAll(IsNotBrickable());

How can I send the desired item tag to the struct?
Everything i’ve tried didn’t work.

It’s untested, but

outOverlappingActors->RemoveAll([itemTag](AActor *RemovalCandidate) {
    ABaseGameplayTagActor *TagActor = Cast<ABaseGameplayTagActor>(RemovalCandidate);

    return TagActor->HasMatchingGameplayTag(itemTag);
});

should do it.

Results in: error C3481: ‘itemTag’: lambda capture variable not found

One way I managed to get it working was the following:
Struct is the same but added the variable: FGameplayTag itemTagToProcess
Created an instance of the struct, set the itemTag and only then used it.

struct IsNotStoreable
{
	FGameplayTag itemTagToProcess;
	bool operator()(AActor *RemovalCandidate) const
	{
		ABaseGameplayTagActor *TagActor = dynamic_cast<ABaseGameplayTagActor *>(RemovalCandidate);

		return !TagActor->HasMatchingGameplayTag(itemTagToProcess);
	}
	void SetGameplayTag(FGameplayTag tag)
	{
		itemTagToProcess = tag;
	}
};

IsNotStoreable test;
test.SetGameplayTag(itemTagToProcess);

outOverlappingActors.RemoveAll([&](AActor *actor)
							   { return test(actor); });

This ended up working, feels weird and poor coding but if someone finds another way please let me know!

The itemTag variable has to be defined somewhere above. It has not been present in your initial example code, so I left it out. Obviously the closure call can’t guess the tag you want to filter for :wink:

Btw. is there a specific reason why you are not using UE style casts? Have a look at this interesting article How Unreal Engine C++ Cast<T> function works?

1 Like

Turns out it didn’t work because it doesn’t capture class variables.
I had itemTag as a class variable that is set on the blueprint object.

To work around this I created a local item tag:

FGameplayTag localItemTag = itemTag;

With this your suggestion worked! Thank you a lot!

I’m using this type of casting as it’s the only method I know but I’m going to check out that article :smiley:

1 Like