Able v3.55 submitted. Notes below:
I seem to have run into a problem. I made a new ability and put in a animation task. However, the ability goes on forever.
Probably canât figure out what your animation length is for some reason. Iâd check that animation clip.
It might just be me, but this happens for any animation I use. To fix this, I mess with the ability properties ability length and then set it back to the default.
Hmm, canât say Iâve ever seen that happen locally, but Iâll look and see if something broke.
I had an issue with channeled conditions that required me to modify the Able code. Pretty sure I mentioned it before in the past. Iâm not sure why the fix has yet to make an appearance in the main code. The problem is some conditions are only checkable on the client side, and not the server side, such as the input conditionals, and the logic for branch and channeled conditions doesnât account for that entirely.
But since functions like UAblChannelingBase::GetConditionResult and the FAblAbilityInstance::CheckChannelConditions that calls it only operate on bools which can be inverted to true when it wasnât able to properly check input.
In reality, there are 3 states that need to be accounted for by all the condition checking code, branch conditionals and channel conditionals. It needs to make a distinction between explicit success and failure and a condition that cannot be checked, so it really needs to be treated as a tri-state check against the activation logic. Where the logic breaks as-is is given the fact that the results can be inverted, such as âinput not pressedâ. GetConditionResult returns false in that situation when it canât properly check, but because the caller lacks the context that the false is due to the inability to check, if the result is inverted, it gets turned into a success and you have the server making branch of channeling decisions based on information it doesnât have. A tri-state would only invert the explicit states, and not the ignored state.
Here are select bits of how I fixed these issues, by changing these bools into a tri-state enumerator, and handling them accordingly.
Note how the input conditional returns an ignored state, distinct from the true/false success/failure it returned before. This represents a distinct state that wonât be mistaken for an explicit success/failure state
By handling these distinct states properly, you ensure that anything involving input conditionals, or any user added realm specific conditionals, can ONLY drive state changes from the appropriate realm(client/server)
Ah, that does ring a bell. Not sure why it got missed either. Thanks @JSwigart
Just a heads up, Iâm in Austin and just got back to my place after 5 days without power / water. Power is back but still waiting on water. Iâm safe and have supplies, but be patient as I get settled back in and try to get back into a normal flow. Hope everyone else is staying safe out there.
Hi .
First off great plugin and glad to hear youâre getting back to normal and safe.
Quick question, If I need my character to instantly rotate to where the camera is facing on ability cast, fully networked, what would be the best way to go about that?
I suggest adding a m_TargetRotation or something that can be set on the context before being sent to the server, then use that to set context ownerâs rotation on all the clients. The TurnTo Task doesnât work here because there isnât a target, and the TurnTo Camera wouldnât work in a networked environment if Iâm not mistaken.
Thanks again for the great plugin
Sorry Iâm just getting to this. Like I said, itâs been a crazy few weeks.
TurnTo should work in the network environment even if you use Camera (but I havenât verified that). Effectively what you want is to turn towards the Camera, which modifies the Player Yaw, which gets replicated to the Server since Client movement is authoritative (to a point). Iâd just try that - if it doesnât work, you could also create a location just infront of your player, set that as the Target Location (which will get replicated up with the Ability call to the server), and you can just set your TurnTo Task Target to Location.
Able v3.56 has been submitted, notes below:
Able v3.57 has been submitted, notes below:
If you arenât on our Discord, Iâd definitely encourage you to swing by. Community is super helpful and you can directly suggest features / reports any issues (like this Initial Stacks concept). You can get a link by opening up the Ability Editor and using âCommunity -> Discordâ.
Able v3.58 submitted, notes below:
As always, please let me know if you run into any issues!
I see the Able system is 50% off until today, and Iâm considering purchasing the product, so I want to ask a quick question: does Able still have conflicts with ALSv4? (Iâm using the C++ version, if thatâs of any relevance.) I was reading through some pages of this thread, but then I realized there are 116 pages. I apologize if this question has already been asked and answered.
That issue is with ALS, not Able unfortunately. I know the fix amounts to basically a nullptr check within ALSâs tick method - but Iâm unsure if the author of ALS is aware of the issue or has put in a fix.
Able v3.60 submitted, notes below:
Hey , how are you?
I canât describe how impressed our team is with Able. I mean, it is everything weâve asked for â thank you so much for putting your time into creating this great piece of software!
Anyways, Iâve been playing with Able this last weekend and compiled a list of questions that I wish you could respond.
- Is there any way to access Blueprint Function Libraries through an Abilityâs Graph? It seems we donât have the WorldContext in there, so Iâm currently not able to access my so precious functions.
- How do I set default Tags at Actors that expose the AblAbilityComponent? Like, I have this Actor called
AWall
and Iâd like it to start with the tagWall
. I believe the only way I found so far is by calling the AddTags at the BeginPlay event. Of course, I can always create a Tag system myself but well⌠- Is there a way for me to prevent an Ability to be activated using Tags as filters, pretty similar to what GAS does? I donât want Players with the
Dead
tag to activate abilities around. - Oftentimes I donât know the length of my ability. I mean, thatâs way too obscure to me. I want this ability to consider itself done as soon as all the tasks are done. In this case, all I have to do is to mark Finish All Tasks, right? Sorry, Iâm a little confused because it seems the Timeline still persists against the Length set at the AbilityProperties.
- Letâs say I want to create a Passive Ability called âRegenHPâ. How do I add this Ability to all characters by default? I mean, should I really Activate the ability manually through BeginPlay or something, or is there any other, correct way?
- I have this Ability âReviveâ. When a Character dies, we trigger an animation and hide the UI. Turns out the UI is client/local-only, but the animation must be run at every connected client in the server. How would you create this Ability? One Task for the UI, and one for the Animation? Would you mind elaborating your approach here?
Now, let me jump into a more complex âquestionâ. Pretty much, sometimes Iâm struggling to differentiate a Task from an Ability; that said, given the following scenarioâŚ
So, a few questions around this, especially regarding good practices.
- Would you recommend creating an Ability âDieâ, that does things, and Activate it when I see the Health reached 0? OrâŚ
- Would you recommend creating a Passive Ability that monitors the Characterâs Health, and when it reaches 0, we activate this other Ability called âDieâ? OrâŚ
- Would you recommend creating a Task âKillâ, that is called from a âDieâ Ability that is activated when the Health reached 0? OrâŚ
- Something else?
I mean, I feel that I am always struggling when making decisions. I donât know what kind of logic I should keep at my own scripts and what logic belongs to Able Abilities. Could you reference any documents that get deeper into the theoretical/conceptual nuances of your system? Or perhaps mentioning some broad Good Practices around the core concepts of Able?
So far I believe thatâs all. Thank you so much for your time and I look forward to your answer!
Cheers,
Gui.
Hey Gui, posting your answers here for posterity.
- Some BP Libraries work fine (Oculus for example), others donât. No idea why. There is obviously some bit that needs to be twiddled - but I havenât found it yet.
- Using the Begin Play is currently the only way, I can likely expose that Tag container. So Iâll look at that for the next update - I canât think of any reason why not off the top of my head.
- There is a âCanAbilityActivateâ check that you can have look at Tags and have all your other Abilities inherit from that so that BP call gets hit.
- The timeline has to be set to some value so you can drag and drop things, but yes, you could just set it to 1 second and as long as you have âMust Finish All Tasksâ - the Ability will take as long as the Task requires. Thereâs just no way for me to know what that time may be to show in the Editor.
- Yes, manually adding things in BeginPlay is the best way. I do that in my own projects. Just make a quick system that takes a list of Abilities to auto apply.
- You can put both Client / Server / Client And Server tasks in the same Ability. The server just wonât execute the Client only tasks, and vice-versa. So make a simple Custom Task that hides your UI if youâre the local player and toss the animation and stuff in there as well.
- A death ability is what I do in my own projects. Basically just loops a dead animation, set some material parameters to fade the model out, and then, once the Ability is done playing, clean up the Actor. If you wanted corpses, you could just spawn in a corpse and do some pose copy - but it all begins with that Death ability.
- No, Damage is an event. There is a OnDamaged Event on the Actor itself, so you know when the Actorâs health is changing and possibly goes to 0. No reason to constantly check.
- Not sure what a Kill Task would do (unless maybe you mean mark the Actor as destroyed or something).
The basic questions I ask myself when deciding how to split logic is:
- Is the logic something simple and holistic that I want to expose to designers? Then itâs probably good for a Task. Doing a collision query, playing an Animation, playing a Particle effect. All simple tools that make for great Tasks. Tasks are your wood, hammer, nails, screws, etc. They are simple things that do one thing only but are fairly useless by themselves.
- Is the logic something I can see building from those pieces and may re-use? Then itâs probably good for an Ability. Abilities are your chairs, tables, etc - all made using using Tasks. Can you have a one-off Ability? Absolutely. If I want to have a background NPC play some animation to act as if heâs talking to another NPC and the other NPC just laughs - I can set that up with Able pretty easily (two abilities - same length, one plays the âtalking animationâ the other is timed to play the laugh when the talking ends and both Abilities are just auto applied when the game starts to their appropriate actors). Thatâs entirely fine. You donât need to do a whole sequencer movie for something like that.
Able is pretty cheap in the grand scheme of things. The network bandwidth is super small, the CPU over head is relative to the number of Tasks you have running in an Ability so tiny Abilities donât take much time. Odds are Physics, Rendering and Character Movement will be your high nails of performance or bandwidth long before Able is. So just do what is works and is easiest - you can always go back and refactor things as needed.
Thank you so much for such a thorough answer, .
I mean, I couldnât be happier with what you wrote. Allow me to contextualize.
Before Able, we created our own AbilitySystem. We donât have an Ability Editor as Able offers, but in terms of Developer Experience, it is awesome. Our pain points were in the semantics: replication, overall performance, etc etc. So we checked GAS out. Unfortunately, GAS is quite imperative and doesnât easily integrate with the thing we created - and, for what itâs worth, if we had to migrate everything from our system to GAS, Iâm talking about months of work (which is the reason we decided to avoid it).
Then we found Able. And it seemed to us that, by design, itâs smaller than GAS and less opinionated. Since it was on sale last week, we decided to give it a go. And after some exploration this weekend, as I mentioned, I stumbled upon all the questions I wrote above.
Now, after reading your answer, I must say that this is the perfect world. Able is almost non-opinionated, giving us the flexibility to use it in pair with the system we created, without having the fatigue of migrating all the things to a brand new system.
I believe the only thing left now is for me to debug further how I can expose BP Function Libraries to Able consistently, b/c I personally adore stateless functions - itâs just a time saver when you gotta refactor something. Oh, and by the way, perhaps 4.27 might be our solution. Check this out. Fingers crossed!
Last but not least, thank you again. That was quick and on point!
Take care my friend,
Gui.
Able v3.61 submitted, notes below:
I bought the plug in today, was really excited to make the switch from GAS for an easier to use solution. I must add that I am trying to do multiplayer abilities and GAS worked fine for that except when It came to lag.
After setting up a simple ability from the tutorials page in the Documentation I tried to run the ability on a client and I keep getting the same crash error no matter if I do an authority check or locally controlled player. Havenât tried server call because I was under the impression that this was networked out of the box. If thats not the case then I really regret spending the 100$⌠Heres the error log and the code Iâm trying to run on my character
When running as the listen server My print strings work and no crash. Running on a client instantly crashes the editor.
(Greggory is on the Discord where weâre helping him).
For posterity, Able is networked outside of the box. There is no need to do anything fancy - this looks like just a bad Ability somehow getting passed into the Context.
EDIT: The crash was caused by a trying to use a latent call with a stale context it looks like.