What's the proper way to reference and destroy gameplay cue notify actors?

So i’m using the gameplay ability system… It’s great… And using static gameplay cues seem to be no problem but when trying to use a notify actor one to hold a flames stream spell particle effect… it remains after the gameplay ability ends and the effect ends…

1 Like

I found a YouTube video in which the tuber suggests setting the “Auto Destroy on Remove” boolean to true. It’s in the Cleanup section.

I am trying to setup a GC for the first time. Blueprint only. It fires off correctly the first time, but not the second. I checked the auto destroy, put a print string on the Destroy event and it is not getting destroyed. 4.24.1.

I found out that i was using Gameplay Cues wrong at first… one thing you need to know is they ONLY exist on clients… Idk if that helps you but it was the root of my problem.

A way I found to tackle this, is to add a “Destroy actor” node in the On Remove function overload. Then it will handle as you want it to.
Just be carefull on how to handle it in case the actor is dead already or you might have crashes :slight_smile:

Sorry to resuscitate this thread, but the issue is still present and this is the thread we endup when we search for this issue.

The problem is AGameplayCueNotify_Actor are usually recycled after remove; that means they are not destroyed and keeps getting reused.

If you are relying on the bAutoDestroyOnRemove setting to restart your effect that is NOT going to work, because this setting only makes AGameplayCueNotify_Actor call GameplayCueFinishedCallback which only ends up destroying the GC if UGameplayCueManager::GameplayCueActorRecycle < 0.

Your options are:

  1. Reset the effect On Active inside the AGameplayCueNotify_Actor
  2. (C++) Override AGameplayCueNotify_Actor::Recycle to return false and prevent recycling
  3. (C++) Override AGameplayCueNotify_Actor::ReuseAfterRecycle to reset the effect
  4. Disable recycling in the UGameplayCueManager
  5. Destroy the actor On Remove inside the AGameplayCueNotify_Actor to prevent recycling. I would not recommend this because the Gameplay Cue systems calls a few more methods after the On Remove handling and it might cause crashes.

I think 1 & 3 are the best because they keep the recycling logic which is a nice optimization to have. The best of the best might to make ReuseAfterRecycle call OnReset Blueprint event so
the reset can be seemlessly implemented in blueprint.

4 Likes

void AGameplayCueNotify_Actor::ReuseAfterRecycle() contains this:

void AGameplayCueNotify_Actor::ReuseAfterRecycle()
{
	SetActorHiddenInGame(false);
}

It passes false so it doesn’t even hide the actor.

void AActor::SetActorHiddenInGame( bool bNewHidden )
{
	if (IsHidden() != bNewHidden)
	{
		SetHidden(bNewHidden);
		MarkComponentsRenderStateDirty();
	}
}

It’s set up to do nothing.

Seems like overwriting void ReuseAfterRecycle() and passing true will result in intended behaviour.

1 Like

Could you provide an example how you would Reset the effect ?

I’ve been struggling a bit with what should have been pretty simple.
an Effect that Enable a GameplayCue on Instant hit (or small duration)
and a simple GameplayCue that trigger a particle explosion

when I tried
2. (C++) Override AGameplayCueNotify_Actor::Recycle to return false and prevent recycling

The first time the Cue will trigger when the Effect start, and another time when it is completed.
And the next times the Cue would trigger only “after” the effect duration is completed.

I’m trying to make it work with cues instead of just spawning the particle on collision from the “bullet” BP cause I need to better understand the Gameplaycue and their limitation.

Regards.

Hello,

Unfortunately I am not able to reproduce the issue on the current UE version I am using.
I would personally expose both Recycle & ReuseAfterRecycle in blueprints

Here is how it could be done in C++ GKGameplayCueNotify_ActorExample · GitHub

I implement my GC setup OnActive and simply hide the Actor on recycle and show it again after recycle

Recycle is the function that hides the actor once it is not needed anymore,
ReuseAfterRecycle() is called before the object is reused, it should make the actor unhidden.

I’m pretty sure it should hide the actor because activation will unhide and you get perfectly defined behaviour when you do. If you don’t the animation will simply keep on playing indicating this is actually a bug.

I was able to find the proper repro step, and it looks like a bug in my version (I have no modification on any engine class)
image

I’m able to have a working behavior where the GameplayCue actor gets removed correctly when the Effect is completed if I change my Period in the effect from 0.2s to 0.21s. I can have a broken behavior if my period is 0.1, 0.2, 0.25 0.5 but if I use something else life 0.12, 0.21 or even 0.255 instead of 0.25 then my cue actor gets removed correctly.

I’ll try to dig deeper in the code to understand why,

Regards

Ah, it’s a networking thing,

Even if I play alone, If i play as a “client”, this is where the error occure,
When I play in StandAlone I see no bugs.

Nice, this is how I was applying the effect

Using this

This website

state that :
If a GameplayCue was Added locally, it should be Removed locally. If it was Added via replication, it should be Removed via replication.

Could it be that my Cue is added locally but the effect is turned out by the server ? unless I’m using a different period in which case the cue is removed locally first ?

Iirc the actor is actually destroyed on standalone and never recycled with auto destroy on remove set.

I though you had something there, cause when I removed the checkbox (auto destroy) the first time I get the effect it gets removed properly after my 2sec duration, regarless of my period time.

I can see the Actor is still attached to the player, but inactive . However the second time I apply the effect it will play endlessly and never gets disabled again.

I had a barebone c++ ability system in place, so I figured I should try with Lyra example, but I have exactly the same behavior.

My theory is still that ReuseAfterRecycle() should not set the actor to visible.

this is the OnRemove_Implementation:

bool AGameplayCueNotify_Actor::OnRemove_Implementation(AActor* MyTarget, const FGameplayCueParameters& Parameters)
{
	if (!IsHidden())
	{
		SetActorHiddenInGame(true);
	}

	return false;
}

Why would they set it to visible again? That’s exactly what remove means. This is also one specific execution path and those who don’t run don’t have problems.

image

In my version it’s already to true, compared to yours that was false.

Must have been something they already fixes

Oh nice then i was right but i only got gas about a week ago. And this must’ve been in there for atleast 3 years.

Butto be clear i really like this system.

@ezgoin I think I’ll love it also, if I can figure this replication issue.

For me any duration works without problems in any mode. I do apply from an ability. I do set

AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Full);

to full iirc it’s needed to replicate the montages.