Intellisense is just generally really slow, bordering on non-functional. If it compiles fine, I think you’re good.
You should probably try fixing the intellisense at least a little for C++ in general, as the UE4 source tends to be a tad big and older VS versions suck quite bad with C++ code. I personally did something involving a /yu keyword or something, that might help?
Thanks for the write up KZJ! I was able to get a GameplayAbility with various GameplayTasks setup that apply a GameplayEffect which executes a damage GameplayEffectExecutionCalculation and properly modifies and replicates health from my AttributeSet on a dedicated server. Only took 4 days haha.
With that being said, I have three questions I’m sure you could help with.
What do I need to do in order to get my AttributeSet attributes to show up in the GameplayEffect’s relevant dropdowns (Modifiers, GameplayCues -> Magnitude Attribute, etc)? I can only capture the attributes when I add my damage GameplayEffectExecutionCalculation to the GameplayEffects Executions array.
SOLVED: Had to remove “meta = (HideInDetailsView)” from my UCLASS definition of my AttributeSet.
What does the setup look like for getting GameplayCues working in GameplayEffects? For instance, the GameplayCue Editor fails to “Hot Reload” with a “ERROR: Can’t save a makefile that has invalid contents. See UBTMakefile.IsValidMakefile()”. What I’ve done so far is: - Implement IGameplayCueInterface (although I realize it isn’t necessary to get GameplayCues working in GameplayEffects)
Added a GameplayCue.Ability.Projectile.Sound.OnHit.Character tag with a GameplayCue_NotifyStatic blueprint as the handler where I override both OnActive and OnExecute functions to just play a sound at a location.
Then I added my GameplayCue tag to my instant damage GameplayEffect.
The GameplayCue never appears to get executed (added a print string to both OnActive and OnExecute).
SOLVED: Ran “Verify” from the Epic Launcher on my UE4 engine files…GameplayCues magically started working afterwards.
Not really a question, but I would love to know how to create my own AbilityTask. I know you mentioned it was out of the scope of the guide, but now that you have the experience implementing them yourself perhaps you would be so kind to share what you’ve learned? I get a whole butt ton of external link errors pertaining to UGameplayTasks that I can’t seem to resolve when I create a new class inheriting from AbilityTask.
Thanks again man! Iv’e had a ton of fun working with the GameplayAbilitySystem and I doubt I could have gotten to where I am without the confidence your guide provided.
Don’t really have time atm, but I’ll try to answer as as I can instead of making you wait another day or so.
Your GameplayCue tag is added in the GameplayCue section of your GPE where you can set magnitude and all, yes? Probably a stupid question, but I figured I’d just throw it out there so as to not risk avoiding the obvious solution.
If it’s not a silly error like that, I’m not sure what you would have trouble with, your setup seems really elaborate, yet GameplayCues work without flaw for me right out of the box. The GameplayCue editor always spits out a hot reload error for me for some reason yet it tends to work in spite of that, so I simply assume it’s more of a warning, rather than an actual error that prevents cues from working period.
Static GameplayCues aren’t really very complex C++ classes so I don’t see where things could go wrong there. Checks if the target for the cue is valid/not a currently pending deletion, calls the generic GameplayCue calling function and then the specific ones depending on which type of event it is, that’s all there is to them. Would your Cue fire if you were to call it manually without a GameplayEffect attached to it? Then you’d at least know if it’s a problem with the GPE calling the Cue or Cues just not working period. Kinda have to poke around a little for what the actual culprit is before you can find a proper solution.
Add “GameplayTasks” to your public dependency modules in the build file, this should solve the bulk, if not all, of your linker errors relating to AbilityTasks.
As I said I don’t have much time to get into it, however tasks aren’t too difficult to get the general gist of once you understand some of their general rules that you can deduce from the tasks already inside the plugin. They usually contain a static function that lets you comfortably create and activate them in BP, they generally always start with their Activate() function, the first delegate declared with one of the DECLARE_DYNAMIC_MULTICAST_DELEGATE macros and marked as UPROPERTY(I do have UPROPERTY(BlueprintAssignable) specified in mine. Not sure if that is necessary though) defines what kind of delegate is used for the exec pins outside of the regular one on said BP creation/activation function(further delegates of a different type that fulfil the criteria will not be considered as exec pins, you can still use them interally though if you find them convenient) and tasks end with their OnDestroy functions(and will also prevent you from broadcasting the delegates that make your exec pins, hence you should always check if the task isn’t already ending before broadcasting a pin using ShouldBroadcastAbilityTaskDelegates()), so you can wrap things up there if there’s a need. Names of the declared delegate variables also describe the names of the exec pins in said BP task node, and calling the Broadcast() functions of these delegates will simply execute the exec pin in BP, optionally filling out the return values of the node with the values specified in your broadcast(as delegates themselves can be defined to have different amounts of return values using different macros like, say, DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams).
There isn’t much more to know about them, they’re simple at core once you understand the modus operandi and most of their stat/ability tracking magic comes from the AbilitySystemComponent itself providing so many delegates itself to clink into and react to anyway. Just look at the code already in the plugin and experiment with it.
I just found some time to try this.
Thanks for all the information, the initial setup is clearly easy with your explanation. I just need to understand more now that I have something working.
I try to follow & understand what the purpose of the strings “ConfirmInput” “CancelInput” and I can’t get it.
It is set as ActionBinding in the BindAbilityActivationToInputComponent but I can’t get where it is really used.
Can anyone explain how it is used ?
What about the ConfirmTargetInputID & CancelTargetInputID ? Is it to be able to map an AbilityInput enum value to cancel & confirm targetting?
Does the ConfirmTarget/CancelTarget is something generic? I’m lost. I bet it is because I didn’t had much time to play with it, but if someone can help I will appreciate.
I try to read some of the abilities that are in the module, and there are lof of them for Targeting & reticle… is it something really generic or more something for Paragon style game.
These strings should define which action mappings are used for the generic confirm/cancel functionality of the Ability System Component, iirc.
Abilities can wait for Confirm/Cancel inputs using ability tasks, and you can also set the ability task that uses targetting actors to confirm the currently selected target/targets upon the Confirm button being pressed. Target Actors themselves aren’t really described thoroughly in this guide, but they essentially let you define ways of getting a target for your ability/buff/whatever. This can be as simple as a targetting actor simply tracing an area/line and throwing out all valid, hit actors in the form of a TargetDataHandle or something more complex and situational(such as maybe a certain location in the world you get with a different unrelated system. I have target actors that work with my own lockon system component, for example). part about target actors may be that you can make the server use the target data of the client if you want to, and even validate it to minimize cheating. This can be useful for top-down strategy-kinda games because you can just ask the client for, say, where he points his mouse at, and it can be useful for shooters that would want to take the client’s word for where they wanted to aim at for responsiveness reasons. It doesn’t always make sense to have the client decide these things, but it’s a useful tool for a variety of different games.
You’re not required to use them if you don’t need them though, at any rate. This kind of feature really only makes sense if you want to separate initial activation of the ability and the actual usage of it(for aiming, etc.), as the Confirm/Cancel input let you set up binds that are consistent for all abilities and even built into the system in such a way that if the Confirm/Cancel bind were to share a key with an ability bind, the generic Confirm/Cancel bind will take priority.
Paragon is a nice and easy to follow example on how and why it is used, but the concepts are applicable in all sorts of games, really. Pressing an ability key in that game that isn’t the default auto-attack on Left-Click(and isn’t some kind of self-buff or aura around you that doesn’t really require a second consideration, anyway) often first prompts a change in state that doesn’t actually consume ressources or triggers the actual effect yet, many abilities with a straight firing projectile/AOE zone will first give you targetting visuals to give an idea where they land, and/or certain abilities like Rampage’s huge stunny rock will play a short startup animation and leave it very obvious you are about to give some poor sod a concussion if they don’t dodge. You may then either Left-Click while in this state(which is the Confirm input) or press Ctrl to get back to your default state, ending the ability without spending any mana or similar such things(because you backed out of the ability prematurely).
Yeah, it is rather complete all things considered. You still need to write your own bits here and there especially if you wish to integrate outside systems into abilities using tasks, but there’s a lot of tiny things already built in that makes managing how, why and when abilities activate very convenient.
TargetDataHandles are a bit weird because Target Datas actually operate on struct inheritance last time I checked, which is why you need a handle in the first place. There’s constructors that make creating these structs and/or their handles easy, but they’re spread out across all sorts of other structs and functions and sometimes you just need to fill out the struct you want yourself, which can be cumbersome/confusing.
TargetActors are also a little weird, because while the “return value” of the target actor, so to speak, is handled in ConfirmTargetingAndContinue, that function does not actually return the targeting info itself, but you should rather broadcast a delegate in there that delivers the target data back to the ability task the actor belongs to. This threw me off when I first tried to get into them, so I’m just throwing that out there now.
The act of giving the client the choice of what to target is rather simple, though. I believe it is just a boolean on either the ability task or the target actors that you can set/override depending on what’s convenient. How you approach what should be serverside and what should be clientside is up to you, I’d probably argue it makes sense to have manual input like mouse/cursor etc. be clientside while things like an AOE debuff around your character that you would use traces for otherwise anyway should probably be serverside.
I must have miss something but I can’t initialize my AttributeSet.
I read that you can load DataAsset to load them, but is it the only way?
In fact, it expects one FGameplayAttributeData per attribute, but the editor don’t have an editor for it and the BP node can’t create one
What step did I missed? Thanks,
Just a little bump in this.
How do you set the default attribute values ?
You can set some in the AttributeSet contructor in C++, but if you have 2 characters and you want them to have 2 different base Health value, what’s your approach?
Are you all settings DataAsset when working with AbilitySystem during prototyping?
I don’t actually know the intended/ way to do this, but I suppose if the DataAsset way is not optimal and everything else fails, maybe simply applying an instant GameplayEffect upon spawning to initialize the values would do the trick?
That’s the I got, anyway. For a better answer I’d have to dive in there and check myself, but I’ve got a bit to do here and there right now, now that the semester properly started and all.
Thanks for creating this tut. I’d really like to use this system for a few different projects. Unfortunately I just started trying to follow this tut and I’m running into a few setup issues.
The header file isn’t found. I added the line below to my build.cs file ad now the project compiles successfully but the IDE still gives me errors about “cannot open source file” on the headers and intellisense won’t work.
PublicIncludePaths.AddRange(new string] { “GameplayAbilities/Source/GameplayAbilities/Public” });
When I step through the character constructor CreateDefaultSubobject seems to work just fine creating the AbilitySystem component but as soon as execution gets to SetupPlayerInputComponent the AbilitySystem is NULL. I’ve followed the tut closely and I don’t think I missed anything, but any idea would be appreciated.
First, thank you so much for your time and effort to post what you have learned. I appreciate it.
I was following your examples up until you modified 's code to fit what you had been doing. I had to make some changes to address some compiler errors.
I am unclear what to change “Damage().HealthProperty,” to.
float DefenseMultiplier = 0.f; //**I changed this from DefensePower
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(Attribute.DefenseMultiplierDef, EvaluationParameters, DefenseMultiplier); //** I changed DefenseMultiplierPowerDef
//Finally, we go through our simple example damage calculation. BaseAttackPower and AttackMultiplier come from soruce, DefensePower comes from target.
float DamageDone = BaseAttackPower * AttackMultiplier * DefenseMultiplier;
//An optional step is to clamp to not take health lower than 0. This can be ignored, or implemented in the attribute sets' PostGameplayEffectExecution function. Your call, really.
//DamageDone = FMath::Min<float>(Damage, Health);
//Finally, we check if we even did any damage in this whole ordeal. If yes, then we will add an outgoing execution modifer to the Health attribute we got from our target, which is a modifier that can still be thrown out by the attribute system if it wishes to throw out the GameplayEffectExecutionCalculation.
if (DamageDone > 0.f)
{
OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(Damage().HealthProperty, EGameplayModOp::Additive, -DamageDone));
}
Edit:
I had put the struct and “Damage()” in the header instead of the cpp. Once I made that change I can move on to the next set of unknown issues.
Oops. I knew I forgot to change one struct name. I think I changed all instances of Damage() to the struct Attributes, and changed the name of the struct type itself to AttStruct? Basically Damage() gave you the struct that would contain the attributes relevant to your gameplay effect execution, in this example the damage execution would need target health, source base damage and multipliers, etc.
I will change this.
The intellisense bit seems to be a known and common issue. If your compiler or your intellisense does any funny business, generating the Visual Studio project files again by rightclicking the UE4 project file in its folder seems to fix the issue most of the time. I think Visual Studio just seems to have difficulties updating the linking changes.
Latter seems like a bit of an odd issue. I don’t think I ever had the issue of the AbilitySystem just flat-out not being there for the Input Component binding. Would FindComponentByClass still work? If it does, you made a mistake setting the pointer variable to your AbilitySystem correctly, and if it doesn’t, then it for some reason it actually refuses to create anything.
Has anyone tried using the UGameplayEffectTemplate? I add properties to the array but everything is still showing in child blueprints so i wonder if the class is broken
@KZJ I’m getting an assertion when applying a gameplay effect to the skill owner:
check(CurrentActorInfo); in GameplayAbility.cpp at line 1490
I’m calling AbilitySystem->InitAbilityActorInfo(this, this); on BeginPlay in my owner actor as well as AbilitySystem->RefreshAbilityActorInfo(); on PossessedBy
EDIT:
This assertion only happens when I set the ability instancing policy to Non-Instanced
I didn’t, sorry. Maybe the Discord can help you. I haven’t seen it be relevant anywhere else in the code I saw though and it seems to be essentially just editor-QoL anyway, so I guess it isn’t THAT bad if it can’t be figured out.
Welp I just checked that code out, looks like someone was a joker(or I’m the joker and just don’t understand why they did that) and decided to check for the ability’s own ActorInfo without providing a way to put an actor info as a parameter/take it from the ability system directly. This is bad precisely because GameplayAbilities set to non-instanced are, well, not instanced and can’t save their own ActorInfo struct to use, so the ability cries error even though there isn’t really a reason to.
Your options would be to either just set the ability to an instanced option, to implement all non-instanced abilities wishing to apply GameplayEffects in C++(because this function DOES exist, it just isn’t exposed to BP), or to expose said C++ function to BP by wrapping around it nicely with a BP-exposed helper function(and then taking the ActorInfo itself from somewhere, either the calling AbilitySystem or just constructing it yourself within the ability).
If i want to cause slow to my enemy with my projectiles. There is anyway to make an effect wait until the effect was applied on the localclient (my enemy) so that could client predict his movement right and avoid reconciliation?
I am trying to take small steps with this plugin. I have successfully applied a gameplayeffect to apply a heal to the attribute set of my character using’s Github project as a guide. I can change the ModifierMagnitude by changing the value in the CDO.
However this approach is not feasible when you want to reuse the class for another character at the same time with a different heal value. I am guessing the CDO change triggers a change back to the previous character to where now they all have the same new value.
I see two paths at the moment. Implement and specify levels or figure out how to manipulate the CDO for classes built on the fly.
I “just” wanted to specify different values for the gameplayeffect for each character without having to create a class for each value.
I am thinking it will be better for me to go the level route.
Side note:
I was able to create gameplayeffect classes on the fly with different values without affecting the prior ones using the testing code in the plugin source, but this breaks down when using a dedicated server as “Def” property is not populated which brings me back to the CDO issue.
Update:
Created a UCurve to assign to the FScaleableFloat and got a prototype working to have different magnitudes based on a “level”.
I really want to use this, and I’ve read it 96 times but I still don’t get it. Is it appropriate to use this for a hunger attribute that gradually increases with time?