It’s hard to diagnose without seeing your setup. If I had to guess, I’d say its likely something broken in your Branching condition, or your looping condition. I’d take things a step at a time and see where the problem is. Start with just doing the Start -> Loop (without the Loop ability actually looping). Then setup the looping logic on the Loop Ability (but don’t add the final branch). The only “trick” with the final branch (to the End ability), is you likely don’t want to use a Branch Task. Instead, just add some logic in the OnAbilityEnd method in your Ability blueprint that manually calls Activate Ability on the Self Actor with the End Ability, that way you avoid any potential issues with conditionals that rely on the same input press or anything like that.
Okay I attempted to approach this in a different way based on a post in this thread I completely missed!
I set up an Animation State that will transition to the Block_Start animation if IsBlocking is set to true. I set the transition to Block_Loop on the ending of Block_Start and transition to Block_End if IsBlocking is false. IsBlocking is set up in the animation event graph to be read from the controller.
I created a new ability and set it up only to have a GamePlayTag as a task roughly landing with the animation Block_Loop to start, with it Looping + Channelling on the input of Block. In the event graph I set the value of IsBlocking on the controller with the Ability Start Event.
I’ve tested this without looping and it works perfectly so my guess is in the looping + channeling that is causing me the issue and I’m just blind to what I’m setting up incorrectly =)
Is there any specific screenshots that would be helpful?
Thanks!
This is exactly how I had it set up, the BlockStart ability branches to the BlockIdle ability and the BlockIdle ability Event Graph was firing the Ability BlockEnd. Without looping this all worked fine it is as soon as I enable looping the chaneling just wouldn’t stop =)
Hmmmm… Can you a screenshot of your Loop + Condition settings? I doubt I’ll see anything but you never know.
Hah no worries! You can see the set up below and “Block” input is set up in the project settings to Left Shift.
I’ve moved the plugin into the project source so I can start muddling around and finding out where I’ve gone wrong so if this doesn’t help I’ll let you know what I find!
That looks correct. This isn’t a passive (if it is, uncheck passive and see what you get) or anything is it? I was actually just looking at that code just to see if I could spy anything that might cause this and I didn’t see anything off the top of my head. Have you verified it’s the Ability that never stops looping and not the animation or some visual issue?
Oh I’m sorry I didnt mention that! As you can see below I have print strings as some debug for the abilities and Ability End / Ability Interrupt never fire. If those don’t fire I don’t currently have a way to remove the blocking flag so I’m relying on the Channeling of a Loop to still fire Ability End. Passive is not set up for this ability that seemed like the wrong approach =)
Okay I’ve got a fix in but I’m not sure it is the right fix. It turns out I’m in an Authoritative mode and the ability pointer is reset without ever telling the instance to finish. I added the else/FinishAbility() which allows it to cancel out of the ability properly. The question I have is what have I done differently in my ability/project settings that might not react in a way you anticipated?
if (!ActiveChanged && m_ActiveAbilityInstance->IsChanneled())
{
if (!m_ActiveAbilityInstance->CheckChannelConditions())
{
// Condition(s) failed
if (!IsAuthoritative())
{
// Pass things along to the server.
ServerCancelAbility(m_ActiveAbilityInstance->GetAbilityNameHash(), m_ActiveAbilityInstance->GetChannelFailureResult());
}
else {
m_ActiveAbilityInstance->FinishAbility();
}
m_ActiveAbilityInstance.Reset();
ActiveChanged = true;
}
}
Thanks again!
Good catch. That change appears to be fine, although I’m curious why I haven’t hit this issue locally when testing channeled abilities. I’ll dig into my perforce history. Likely I’ll add that change in the next update sometime this week (waiting to see if any other issues arise), assuming I don’t run into issues locally.
Glad you were able to figure things out so quickly!
EDIT: Small change, you need to preserve the failure result:
// Condition(s) failed
if (!IsAuthoritative())
{
// Pass things along to the server.
ServerCancelAbility(m_ActiveAbilityInstance->GetAbilityNameHash(), m_ActiveAbilityInstance->GetChannelFailureResult());
}
else
{
**InternalCancelAbility(&m_ActiveAbilityInstance->GetAbility(), m_ActiveAbilityInstance->GetChannelFailureResult());**
}
Thanks! I’ll tweak my local copy for the time being then switch back after the next update.
I’m back! =)
I decided to test this a couple different ways to make sure I’m not missing anything else before I dive too far. I just attempted the same build (with the IsBlocking set to Replicated) to test networked responses. If the client is set up as the Authority everything works as planned with the little tweak. If I run two clients the Authority works properly and the animation replicates on the !Authority client. Switching to the !Authority client and run the ability and it gets stuck in the middle of channeling with no firing of Ability End.
It looks like the problem is in the UAblChannelingInputConditional.CheckConditional() as it always returns true if the AbilityComponent->IsNetworked() && !AbilityCompontent->IsOwnerLocallyControlled(). With logging this on the second client I was able to see that it was running that code on the client not just on the server and never able to let go of the channeling ability. I’m wondering if I’m missing a piece of code that submits the Input check from the client to the server for letting go of channeling or if I need to add something to the released input event?
A quick note this behaviour happens if running one client with a dedicated server for testing.
Thanks!
The ServerCancelAbility call should be the one who takes care of that (server obviously can’t check input, so when the condition fails, the client notifies the server who then replicates out the result). Change that previous code to this and see what you get:
if (!ActiveChanged && m_ActiveAbilityInstance->IsChanneled())
{
if (!m_ActiveAbilityInstance->CheckChannelConditions())
{
// Condition(s) failed
CancelAbility(&m_ActiveAbilityInstance->GetAbility(), m_ActiveAbilityInstance->GetChannelFailureResult());
m_ActiveAbilityInstance.Reset();
ActiveChanged = true;
}
}
The CancelAbility code will make sure to forward cancellation request if the the game is networked and then process internal cancel as well if the owner is locally controlled (otherwise it’ll cancel the ability after the server sends out the updates).
Just tried that as a test however the problem is on the remote client AbilityComponent->IsOwnerLocallyControlled() is always returning false? This is especially where my less than 40 hours in Unreal starts to show!
Thanks
FYI: Able is now $99. The plan was always to drop the price a bit after the system had solidified (early adopters have been amazing with feedback and bug reporting), and after the sale I was happy with how the system held up under a bunch of new users - so, I’m comfortable with moving the price down a bit so more people can have access to Able.
Enjoy.
That’s expected. That client should stop the Ability using the OnServerActiveAbilityChanged callback (which is set once the server resets the Active ability on its’ end).
Okay with that in mind CheckConditional will always return true which means the Tick on the component will fail to send any cancel as m_ActiveAbilityInstance->CheckChannelConditions() will always return true. Am I missing something? I’m not sure where else from the remote side it will check the condition and cancel on the input?
Correct. The Remote side always assumes it passes. It’s up to the server to cancel it.
The flow for a Cancelled Channel looks like this:
Authoritative (Local) Client:
Check Channel Conditions -> Input Condition Failed -> Send Failure to the Server -> Server clears the Active Ability -> All clients receive this change and cancel the Ability as well.
UnAuthoritative (Remote) Client:
Update Active Ability -> If it's channeled -> Check Channel Conditions -> Always Pass
OnServerActiveAbilityChanged:
Update Active Ability (or Reset it if the Server cancelled things).
I’ll be able to play with this tonight and verify if there is some bug in that logic.
Hi @, so a couple things:
So I’m not to sure what the functional distinction is between the two nodes “Activate Ability” and the other node “Activate Ability” they’re named the same thing, but one doesn’t support a “target” field, what’s the intended use case or benefit for having both of these?
Also I’m still having issue with cool down (my own user error more than likely).
When the ability reaches cool down, I want it to no longer be able to execute the following logic until the cool down is over.
The problem is that after the first “cool down” the next time ability is able to execute again, it fails to trigger the next cool down (allowing it to execute multiple times without being blocked by a cool down). I have the cool down hooked up to print screen so I can monitor when it’s true or false, and I see that it cool down doesn’t become “true” again until several executions later.
It’s almost like the “cool down” feature has it’s own cool down preventing it from triggering “cool down” because it’s still cooling down from it’s own cool down…did that make sense?
Unrelated, but in task properties under “Branch”, I want to use “custom” in the “conditions” section, however there is nothing to define after selecting “custom”. What custom event is it assuming, I thought this could be user defined before?
Thanks that would be helpful, if you need anything let me know!
For the price change I’m surprised by a drop, I paid the full price before the sale thinking I still got a good deal!
Hey Aumaan,
Can you get me a screenshot where you are checking this cooldown and of the Ability itself (or if you want to package up the project, I can take a look that way as well)? I’m still not totally following what you are trying to achieve vs what you are seeing.
This is the behavior you should be seeing.
- Cast Ability A (which lets say has a 1 second cooldown).
- Immediately try to cast Ability A again - Fail due to cooldown.
- After 1 second, Cast Ability A again - Success. Rinse, repeat.
Now, the cooldown is per Actor, so if you are trying to do a “universal” cooldown or something like that, it wouldn’t work. But you’re saying you’re seeing the Ability fail initially (due to cooldown), but then other attempts succeed even before the cooldown is completed?
Also, is this a networked game or just local?
@RodentGames, Yea it’s been planned for a while. I had promised myself I would drop the price after a few months once I was sure Able could handle more users, so I just decided to finally go through with that.