Announcement

Collapse
No announcement yet.

Able Ability System Info and Support Thread

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    ExtraLifeMatt Hi Matt, I wanted to alert you to another problem we've encountered with Passives. If you have a passive ability that uses PlayAbility to spawn a couple more passives on the same actor, there is a crash (exception in editor) that can occur. If you look in the TickComponent code where you update Passives, you're using this loop with an iterator:

    for (UAblAbilityInstance* Passive : m_PassiveAbilityInstances)

    If any of the InternalUpdateAbility(Passive,...) calls spawn new passives (like in the case above) then the m_PassiveAbilityInstance array will be modified. We've had a few crashes when this happens so I changed the code to do a reverse iteration like so:

    for (int idx=m_PassiveAbilityInstances.Num()-1; idx >= 0; idx--)

    This should allow for removals and additions (though adds will be skipped in the current iteration) without throwing any exceptions. You may choose to solve it a different way, but I wanted to let you know there was a problem.

    Thanks,
    Mike

    Leave a comment:


  • replied
    Originally posted by ExtraLifeMatt View Post

    Interesting... I would expect those values to be different (unless you happen to have a local passive play immediately as a replication comes in - at the same frame, which shouldn't be possible given how the order of operations happen). The easy fix is to simply always walk the passives list when we get a replication notification from the server for those fields. Basically make

    PassiveChanged = PrePendingPassiveCount != m_PassiveAbilityInstances.Num() || ReplicatedPassivesThisFrame;

    Thanks for the report, I'll do some digging and get a fix.
    ok, thanks for looking into it. I'll also add some logging and continue to see if there is something else weird on my end.

    EDIT: I did verify that the PassiveChanged logic is the issue. It detects removals fine, just not adds.

    Edit #2: ExtraLifeMatt " when we get a replication notification from the server for those fields." -- I just re-read that. The problem is actually on the server side, not the client. The server doesn't send the values to the client in the case I mentioned above. The passives go into m_PassiveAbilityInstances locally on the server, but nothing causes them to move into m_ServerPassiveAbilities unless it gets past the PassivesChanged check. It could also be that your cachedPassiveSize set is too late. I didn't investigate that. I only added a bool that said passives changed that fram. The set of cached passive size does happen right after the active ability update, which is responsible for creating the passive, so perhaps the cache check should be above that?
    Last edited by jimmay.10; 08-15-2018, 09:33 AM.

    Leave a comment:


  • replied
    Originally posted by Rthomp01 View Post
    Hey Matt,

    I'm having some trouble getting the CancelAbility task to perform how I'd expect.

    I'm using an active ability called HealOverTime to play some effects, add a tag to the player and play a looping passive ability on the player called RegenerateHealth. For the passive ability, I want to use the CancelAbility task to check if the player is at full health, if not it keeps looping and healing, if they are then cancel the RegenerateHealth ability. I'm overriding the ShouldCancelAbility function in the abilitie's event graph but can't reach any breakpoints inside the blueprint. In the source, the task always exits after this line:

    void UAblCancelAbilityTask::OnTaskStart(const TWeakObjectPtr<const UAblAbilityContext>& Context) const
    {
    check(Context.IsValid());

    Super::OnTaskStart(Context);

    TArray<TWeakObjectPtr<AActor>> TaskTargets;
    GetActorsForTask(Context, TaskTargets);

    for (TWeakObjectPtr<AActor> TargetActor : TaskTargets)
    {
    if (TargetActor.IsValid())
    {
    continue;
    }

    ...
    }
    ...
    }

    My target is self and the actor pointer is valid at this point (makes sense since it just continues then exits).

    So I'm not sure if I'm misunderstanding the intended use of the cancel ability task or if it's even sensible to use an active ability to add a passive ability and have it loop indefinitely in this way.
    Sorry for the delay on this reply, Epic's forums don't like notifying me about posts here from some reason...

    Ah, that should be a "if (!TargetActor.IsValid())", weird... not sure how that bug got in. I'll get a fix in ASAP.
    Originally posted by mikecoker View Post
    ExtraLifeMatt Can you please help me understand your vision of how networked abilities should work? Say I have an AoE ability that stuns a bunch of characters in an area. This ability is responsible for doing a collision query (server side) and then for each target playing the stunned ability (server side) on them. The actual stun ability is marked as a passive and has a custom event (server side) to disable controls and a particle fx task (client side) that should play on all characters.

    I would expect that particle to play on all clients. I've looked at the code that creates the new ability to play and it ultimately calls AbilityComponent ActivateAbility. That code does a check to see if it is authoritative and if so (it is) it calls internalStartAbility. It sees it is a passive and goes through the ActivatePassiveAbility. I can't see where this is getting sent to the clients to also activate the passive. The result is that I don't see that particle fx play on the clients but I do see it on the local client for the server.

    Is there something I'm missing here?

    EDIT: Actually, I see you're using the m_PassiveAbilityInstances to replicate passives. Unfortunately in the TickComponent the PrePendingPassiveCount and m_PassiveAbilityInstances.Num seem to be the same so PassivesChanged is false. ALso, I am running PIE with a single process to test multiplayer.
    Interesting... I would expect those values to be different (unless you happen to have a local passive play immediately as a replication comes in - at the same frame, which shouldn't be possible given how the order of operations happen). The easy fix is to simply always walk the passives list when we get a replication notification from the server for those fields. Basically make

    PassiveChanged = PrePendingPassiveCount != m_PassiveAbilityInstances.Num() || ReplicatedPassivesThisFrame;

    Thanks for the report, I'll do some digging and get a fix.

    Leave a comment:


  • replied
    ExtraLifeMatt Can you please help me understand your vision of how networked abilities should work? Say I have an AoE ability that stuns a bunch of characters in an area. This ability is responsible for doing a collision query (server side) and then for each target playing the stunned ability (server side) on them. The actual stun ability is marked as a passive and has a custom event (server side) to disable controls and a particle fx task (client side) that should play on all characters.

    I would expect that particle to play on all clients. I've looked at the code that creates the new ability to play and it ultimately calls AbilityComponent ActivateAbility. That code does a check to see if it is authoritative and if so (it is) it calls internalStartAbility. It sees it is a passive and goes through the ActivatePassiveAbility. I can't see where this is getting sent to the clients to also activate the passive. The result is that I don't see that particle fx play on the clients but I do see it on the local client for the server.

    Is there something I'm missing here?

    EDIT: Actually, I see you're using the m_PassiveAbilityInstances to replicate passives. Unfortunately in the TickComponent the PrePendingPassiveCount and m_PassiveAbilityInstances.Num seem to be the same so PassivesChanged is false. ALso, I am running PIE with a single process to test multiplayer.
    Last edited by jimmay.10; 08-13-2018, 05:06 PM.

    Leave a comment:


  • replied
    Hey Matt,

    I'm having some trouble getting the CancelAbility task to perform how I'd expect.

    I'm using an active ability called HealOverTime to play some effects, add a tag to the player and play a looping passive ability on the player called RegenerateHealth. For the passive ability, I want to use the CancelAbility task to check if the player is at full health, if not it keeps looping and healing, if they are then cancel the RegenerateHealth ability. I'm overriding the ShouldCancelAbility function in the abilitie's event graph but can't reach any breakpoints inside the blueprint. In the source, the task always exits after this line:

    void UAblCancelAbilityTask::OnTaskStart(const TWeakObjectPtr<const UAblAbilityContext>& Context) const
    {
    check(Context.IsValid());

    Super::OnTaskStart(Context);

    TArray<TWeakObjectPtr<AActor>> TaskTargets;
    GetActorsForTask(Context, TaskTargets);

    for (TWeakObjectPtr<AActor> TargetActor : TaskTargets)
    {
    if (TargetActor.IsValid())
    {
    continue;
    }

    ...
    }
    ...
    }

    My target is self and the actor pointer is valid at this point (makes sense since it just continues then exits).

    So I'm not sure if I'm misunderstanding the intended use of the cancel ability task or if it's even sensible to use an active ability to add a passive ability and have it loop indefinitely in this way.

    Leave a comment:


  • replied
    Originally posted by KamiSkilletLTD View Post
    I can confirm you resolved the socket rotation. TY
    Excellent! Happy to hear.

    Leave a comment:


  • replied
    I can confirm you resolved the socket rotation. TY

    Leave a comment:


  • replied
    Originally posted by ExtraLifeMatt View Post
    Able v2.25 has been submitted.

    Notes:
    • Added support for UE 4.20
    • Fixed an issue where the socket rotation (for targeting or playing various effects at a location) was in the wrong transform space.
    • Fixed an issue where CalculateCooldown would return 0 by default, rather than the specified cooldown.
    • Added a few more guards to prevent a crash that could occur if you had an Ability Component playing an Ability when it was Garbage Collected.
    • Added a few more gaurds to prevent a crash with Verbose mode.
    As always, please let me know if you run into any issues. And if you can provide a repro for a crash (or a simple project showing the issue) - that is always welcomed and helps me diagnose things quickly.
    Glad you were able to fix the bug I reported. Excellent support!

    Leave a comment:


  • replied
    Able v2.25 has been submitted.

    Notes:
    • Added support for UE 4.20
    • Fixed an issue where the socket rotation (for targeting or playing various effects at a location) was in the wrong transform space.
    • Fixed an issue where CalculateCooldown would return 0 by default, rather than the specified cooldown.
    • Added a few more guards to prevent a crash that could occur if you had an Ability Component playing an Ability when it was Garbage Collected.
    • Added a few more gaurds to prevent a crash with Verbose mode.
    As always, please let me know if you run into any issues. And if you can provide a repro for a crash (or a simple project showing the issue) - that is always welcomed and helps me diagnose things quickly.

    Leave a comment:


  • replied
    Originally posted by jfaztk View Post

    I was able to fix it by using dynamic montages instead and just passing it through a slot; blending now works fine. Is there any real downside to using dynamic montages over the ability state? Thanks!
    It just varies based on your needs. If you don't do a lot of variable types of blending, the Ability state works great (it's what I use in my own games). But if you are doing something blend heavy, I could see using Dynamic Montages instead.

    Leave a comment:


  • replied
    Originally posted by ExtraLifeMatt View Post

    Can you post a screenshot of your State Machine setup? Particularly with how your locomotion state is set to blend with the Ability state? If it works while idle, it sounds like there's just something wrong in the locomotion + Ability blending.
    I was able to fix it by using dynamic montages instead and just passing it through a slot; blending now works fine. Is there any real downside to using dynamic montages over the ability state? Thanks!

    Leave a comment:


  • replied
    Originally posted by jfaztk View Post
    Hey Matt,

    I'm having some issues blending with state machines. I have my normal locomotion state which is connected directly to the ability state, with the only conditional being whether an ability is active or not. It works fine aside from the blending; if I turn blending off, or lower the time to a very minimal degree (<0.03) the animation plays fine. But there is no blending. If I enable blending, then when I am idling it actually works fine, but if I use an ability in the middle of running, it'll start at a random spot in the ability animation (probably correlated to the frame of the running animation). This is unusable because it tends to skip a large portion of the animation; I put an AnimNotify in the beginning and it never got fired except when I was idle or when blending was disabled. Any idea what could be causing this?

    Thanks again!
    Can you post a screenshot of your State Machine setup? Particularly with how your locomotion state is set to blend with the Ability state? If it works while idle, it sounds like there's just something wrong in the locomotion + Ability blending.

    Leave a comment:


  • replied
    Originally posted by AngeIV View Post
    If you use animations that have a blend in and blend out (like montages) if you cancel ability, or branch to a different ability - it will not blend out but terminate the animation immediately in one frame. if the ability is shorter then the anim montage it will as well terminate the montage in 1 frame at the time the ability ends.
    Thanks for the reply! I'm neither cancelling/branching nor using montages; I have the ability state set up and this occurs simply when using the ability once. Not only that but blending out isn't even the issue right now, it's blending in (I'm assuming) because the animation begins later than it should if I'm moving around and then use it. Early AnimNotifies do not fire with it as well.

    Leave a comment:


  • replied
    If you use animations that have a blend in and blend out (like montages) if you cancel ability, or branch to a different ability - it will not blend out but terminate the animation immediately in one frame. if the ability is shorter then the anim montage it will as well terminate the montage in 1 frame at the time the ability ends.

    Leave a comment:


  • replied
    Hey Matt,

    I'm having some issues blending with state machines. I have my normal locomotion state which is connected directly to the ability state, with the only conditional being whether an ability is active or not. It works fine aside from the blending; if I turn blending off, or lower the time to a very minimal degree (<0.03) the animation plays fine. But there is no blending. If I enable blending, then when I am idling it actually works fine, but if I use an ability in the middle of running, it'll start at a random spot in the ability animation (probably correlated to the frame of the running animation). This is unusable because it tends to skip a large portion of the animation; I put an AnimNotify in the beginning and it never got fired except when I was idle or when blending was disabled. Any idea what could be causing this?

    Thanks again!

    Leave a comment:

Working...
X