[UE5] How to Bind Gameplay Abilities (GAS) to Input Actions

แชร์
ฝัง
  • เผยแพร่เมื่อ 1 ก.พ. 2025

ความคิดเห็น • 39

  • @MHY-m4b
    @MHY-m4b 3 หลายเดือนก่อน +1

    Hey, thanks for the tutorial. This really did help.

  • @kalin346
    @kalin346 10 หลายเดือนก่อน +3

    we miss you leonard please come back

    • @umbral_studios
      @umbral_studios  8 หลายเดือนก่อน

      I'm sorryyy I've been meaning to make it up to you guys it's just been very tough to make content 😭

  • @jafogx
    @jafogx 10 หลายเดือนก่อน +6

    Using some responses here and a lot of digging I managed to get the system working with the EnhancedInput System and the main tutorial project that includes replication. If anyone is following the main tutorial and stuck there as I was, hopefully this solution helps you:
    1. On your CharacterBase Class, change CharacterAbilities property to a Map That will contain an InputAction as Key and a GameplayAbility as a Value:
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Abilities")
    TMap CharacterAbilities;
    *This is so later on the editor you will go to your character class defaults and add any abilities you want your character to have from the start.
    2. Create another property on the same class, which holds a map of InputActions and AbilitySpecHandles:
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Abilities")
    TMap InputToAbilityMap;
    3. On the same CharacterBase class, change the AddCharacterAbilities functionality to go through the elements of the CharacterAbilities map, calling GiveAbility() on each one of them. Then use the abilityHandle you create in this step to populate the map in step #2:
    ```
    for (const auto& Entry : CharacterAbilities)
    {
    // Get the InputAction and GameplayAbility from the TMap
    UInputAction* InputAction = Entry.Key;
    TSubclassOf StartupAbility = Entry.Value;
    UE_LOG(LogTemp,Warning,TEXT("Giving Abilities to AbilitySystemComponent with default values..."));
    FGameplayAbilitySpecHandle AbilityHandle = AbilitySystemComponent->GiveAbility(
    FGameplayAbilitySpec(StartupAbility, StartupAbility.GetDefaultObject()->AbilityLevel, StartupAbility.GetDefaultObject()->AbilityID , this));
    UE_LOG(LogTemp,Warning,TEXT("Ability Name: %s"), *StartupAbility.GetDefaultObject()->GetName());
    // Add the InputAction and AbilityHandle to the map
    UE_LOG(LogTemp,Warning,TEXT("Adding InputAction %s and AbilityHandle %s to Map"), *InputAction->GetName(), *AbilityHandle.ToString());
    InputToAbilityMap.Add(InputAction, AbilityHandle);
    }
    ```
    Notes: My custom GameplayAbility class is called UCharacterGameplayAbility but your name might vary. Also the parameters in GiveAbility() for the AbilityLevel and the AbilityID are structured different from how it's done on the main tutorial, this is because I have this properties set on my CharacterGameplayAbility header file:
    //Level of ability to grant.
    UPROPERTY(EditDefaultsOnly)
    int32 AbilityLevel = 1;
    //InputID for the ability
    UPROPERTY(EditDefaultsOnly)
    int32 AbilityID = 0;
    You don't need to do this and since at this point we're just granting the abilities with default values anyway you can change StartupAbility.GetDefaultObject()->AbilityLevel and StartupAbility.GetDefaultObject()->AbilityID with a 1 and a 0 respectively, directly on the call to GiveAbility().
    4.On your player character class, modify the BindASCInput() function to go through the map created on step #2 and call SetInputBinding for each of the AbilitySpecHandles in the map:
    ```
    for (const auto& Entry : InputToAbilityMap)
    {
    // Get the InputAction and GameplayAbility from the TMap
    UInputAction* InputAction = Entry.Key;
    FGameplayAbilitySpecHandle AbilityHandle = Entry.Value;
    // Bind the ability to the input action
    AbilitySystemComponent->SetInputBinding(InputAction, AbilityHandle);
    }
    ASCInputBound = true;
    ```
    This function should be called from your SetupPlayerInputComponent() function and also your OnRep_PlayerState() function in the character player, if you've been following the main guide.
    5. We need to initialize the InputComponent in the AbilitySystemComponent class somewhere else than BeginPlay(), since that's too late in the workflow from when SetInputBinding() and TryBindAbilityInput() are called. For this I used OnGiveAbility(), and Added a boolean property to the header file to keep track of when the InputComponent has been already setup (So it doesn't do it again for every ability that's granted to the ASC. (Note that my custom ASC class is called CharacterAbilitySystemComponent but yours might have a different name, if you're following the main tutorial it could be DemoAbilitySystemComponent or something similar):
    void UCharacterAbilitySystemComponent::OnGiveAbility(FGameplayAbilitySpec& AbilitySpec)
    {
    UE_LOG(LogTemp,Warning,TEXT("OnGiveAbility Called"));
    Super::OnGiveAbility(AbilitySpec);
    if(!bInputComponentInitialized)
    {
    InitializeInputComponent();
    }
    }
    InitializeInputComponent() is a function that I created and declared on the ASC class, it gets the InputComponent from the controller and assigns it to the ASC:
    void UCharacterAbilitySystemComponent::InitializeInputComponent()
    {
    // Assuming 'Owner' is actually a UPlayerState*
    ALunaRPGPlayerState* Owner = Cast(GetOwner());
    if (IsValid(Owner))
    {
    // Get the Pawn that is associated with this PlayerState
    APawn* OwnerPawn = Owner->GetPawn();
    if (IsValid(OwnerPawn))
    {
    // Get the PlayerController that possesses this Pawn
    APlayerController* PC = Cast(OwnerPawn->GetController());
    if (IsValid(PC) && PC->InputComponent)
    {
    InputComponent = CastChecked(PC->InputComponent);
    UE_LOG(LogTemp, Warning, TEXT("CASC->SetupInputComponent(): Initialized InputComponent from PlayerController %s"), *PC->GetName());
    bInputComponentInitialized = true;
    }
    }
    6. Finally, in the UnrealEditor on your Character blueprint under the class defaults, you should have a property called Character Abilities, where you can add any GameplayAbilities you want to add and their ActionInputs.
    Once you run the game they should be grabbed from here, bound to the Action inputs and you should be able to use them.
    I hope this helps anyone stuck at this point, any recommendations to improve are welcome as I'm also new and learning.

    • @Smidgon
      @Smidgon 8 หลายเดือนก่อน

      Hi im following your comment just to try get it working and im unsure about
      void UCharacterAbilitySystemComponent::InitializeInputComponent()
      {
      // Assuming 'Owner' is actually a UPlayerState*
      ALunaRPGPlayerState* Owner = Cast(GetOwner());
      if (IsValid(Owner))
      {
      // Get the Pawn that is associated with this PlayerState
      APawn* OwnerPawn = Owner->GetPawn();
      if (IsValid(OwnerPawn))
      {
      // Get the PlayerController that possesses this Pawn
      APlayerController* PC = Cast(OwnerPawn->GetController());
      if (IsValid(PC) && PC->InputComponent)
      {
      InputComponent = CastChecked(PC->InputComponent);
      UE_LOG(LogTemp, Warning, TEXT("CASC->SetupInputComponent(): Initialized InputComponent from PlayerController %s"), *PC->GetName());
      bInputComponentInitialized = true;
      }
      }
      as InputComponent is saying undefined is there an include that is needed for that or is it defined somewhere i dont seems to have it from the main tutorial?

  • @yerha2483
    @yerha2483 11 หลายเดือนก่อน +2

    Thanks for sharing. I intergrated this to my ASC class. I realize this implementation only works for standalone, because clients cannot get the `handle` when `giving abilities`, and server doesn't have any valid InputComponent. So if you are developing multiplayer games, need to change code a bit. You can override `OnGiveAbility` function in ASC, from there clients have oppotunity to get AbilitySpec [contains handle member], so you can call `SetInputBinding` function defined by this video.

    • @manhnguyentien57
      @manhnguyentien57 10 หลายเดือนก่อน +1

      Can you give more details? Im struggling to this

    • @maskwaGaming
      @maskwaGaming 10 หลายเดือนก่อน +1

      Code snippet would be appreciated :)

    • @yerha2483
      @yerha2483 10 หลายเดือนก่อน

      I Implement GAtoIA in another way, you can check yerha/Unreal_GAtoIA repo to get code.@@manhnguyentien57

    • @yerha2483
      @yerha2483 10 หลายเดือนก่อน

      I implemented GA to IA in another way, please check Unreal_GAtoIA repo if you need.@@manhnguyentien57

  • @blobbb
    @blobbb ปีที่แล้ว

    This is actually perfect. Been looking for a good explanation on this for a while.

  • @ParadoxISPower
    @ParadoxISPower ปีที่แล้ว

    He's back 👏 your videos are informative as always! thanks to your inspiration with the original videos I've learned how to program in cpp and bound the abilities to the enhanced input system from there. Also figured out how to clamp the attributes in cpp as well. It's all about overriding the functionality epic built into the gas system.

    • @umbral_studios
      @umbral_studios  ปีที่แล้ว +2

      That’s awesome thank you so much for your support!!

    • @ParadoxISPower
      @ParadoxISPower ปีที่แล้ว

      @@umbral_studios My pleasure, happy to see you back in action!

  • @SPanZeto
    @SPanZeto ปีที่แล้ว

    Oh so you are back!! 🎉🎉❤🎉

  • @SLAPMYGORILLA
    @SLAPMYGORILLA ปีที่แล้ว

    Great quick tutorial.

  • @akashsalvator5220
    @akashsalvator5220 หลายเดือนก่อน

    Can I use GAS to create Attribute system like Strength, Dexterity, intelligence. And this attributes will effect the health, damage, mana. and player can assign this attributes to character to build powerfull character?

  • @bebel9349
    @bebel9349 ปีที่แล้ว +1

    Thank you so much for all your videos on GAS, they're very useful!
    Tho, I have a question, as I'm trying to do the setup in c++. In this video, you get the gameplay ability handle simply right after its creation. However, in the GAS complete tutorial, the abilities are created in the "AddCharacterAbilities()" function which is called in the Character's method "PossessedBy(AController* NewController)".
    The input setup is done in another function called "BindASCInput()" called in the "OnRep_PlayerState()" function.
    How do I get the ability handles from there? Especially considering that I have multiple abilities? Do I need to bind every single one of them manually (if that's the simplest way to go then I'll go for it) to my actions?
    Anyways, again, thank you for your videos.

    • @umbral_studios
      @umbral_studios  ปีที่แล้ว

      No problem I'm glad the videos have been helpful! Regarding your question:
      You might be able to change the `TArray StartingAbilities` field to a `TMap` where the key is an `InputAction` and the value is a `GameplayAbility`. In `AddCharacterAbilities`, you could then iterate through the key-value pairs and first give the ability to the player (which returns the handle you need) and then bind it to the input action, both of which come from the current key-value pair your for-loop is on. Something like this:
      ```
      for (const auto& Entry : StartingAbilities)
      {
      // Get the InputAction and GameplayAbility from the TMap
      UInputAction* InputAction = Entry.Key;
      UGameplayAbility* GameplayAbility = Entry.Value;
      // Give the ability to the current character
      // FGameplayAbilitySpecHandle AbilityHandle = AbilitySystemComponent->GiveAbility(...);
      // Bind the ability to the input action
      AbilitySystemComponent->SetInputBinding(InputAction, AbilityHandle);
      }
      ```
      Does that make sense?

    • @bebel9349
      @bebel9349 ปีที่แล้ว

      @@umbral_studios That makes a lot of sense, thank you!

    • @bebel9349
      @bebel9349 ปีที่แล้ว

      @@umbral_studios Update: I was able to do everything, but there's one exception. When I bind the ability to the input action at the time of giving the abilities, it is too early for the AbilitySystemComponent which has not set its InputComponent yet. Therefore I have to wait for the Ability System Component to have set its InputComponent to bind my abilities. So where or when do I bind the input actions?

    • @UnrealMomon
      @UnrealMomon 11 หลายเดือนก่อน

      @@bebel9349 This is an old reply so idk if you figured it out, but there is an event that runs when the controller possesses a pawn/character. I imagine that event is where you could do that. Because if the controller has possessed the pawn then the input component should be ready as well.

  • @TheShmexyJokerette
    @TheShmexyJokerette ปีที่แล้ว +1

    Can you do a tutorial where you use GAS to connect input actions to an action bar by the player at runtime? Like in some games where you can drag and drop spells to different action bar slots and it binds the inputs that way. Great tutorial! Thank you!

    • @ParadoxISPower
      @ParadoxISPower ปีที่แล้ว

      That would be similar to a drag and drop inventory system. You would create a spellbook widget and a hotbar widget, then an ability widget, bind the slots to your inputs and make a function that gives the ability to the character and binds it to the input when you drop it in the slot

    • @TheShmexyJokerette
      @TheShmexyJokerette ปีที่แล้ว

      @@ParadoxISPower Ahh I see. Thank you so much!

  • @stenichqwet6900
    @stenichqwet6900 ปีที่แล้ว +1

    Yo, I still need help with target actor and wait target data that work for moba like game. Current problem is hit result dont set it on server(multiplayer) and I think its need something different.

    • @umbral_studios
      @umbral_studios  ปีที่แล้ว

      Hey there! Can you please describe in greater detail what it is you are trying to do?

    • @stenichqwet6900
      @stenichqwet6900 ปีที่แล้ว

      @@umbral_studios TopDown game, imagine teleportation ability. So you press button and have accept/cancel with target actor stick to your cursor. Left click accept - you tp to the mouseover location. For single player it was not a problem just with hit result under cursor, but in multiplayer I was spawned in 0.0.0.

    • @umbral_studios
      @umbral_studios  ปีที่แล้ว

      its difficult to say without seeing the project, but I remember running into a similar problem myself. I believe it had something to do with the ability replication policy and/or input replication-have you tried messing around with those settings?

  • @SLAPMYGORILLA
    @SLAPMYGORILLA ปีที่แล้ว

    Do 'Wait Input' Functions still work with this? I read in Tranek's documentation that Wait input functions require Ability Input ID set up on the ability class to execute

    • @vladyslavsorokin2220
      @vladyslavsorokin2220 11 หลายเดือนก่อน +1

      It will work, because the InputID of the Ability is set in the UEnhancedInputAbilitySystem in SetInputBinding.
      Here:
      if (BindingAbility)
      {
      BindingAbility->InputID = AbilityInputBinding->InputID;
      }

  • @Bocatius
    @Bocatius ปีที่แล้ว +1

    Does it work also in multiplayer?

  • @MemberBenefit
    @MemberBenefit ปีที่แล้ว

    Thanks for a great GAS video series! I've implemented a system based on your videos but maybe you can help me with one thing. I have a working system with attributes and abilities for player but I'm trying to find out what should I do for mobs? Should I recreate all the sets of C++ classes for mobs or there can be a better way? I think If I go with a single ability system I will have lots of properties that are not needed on mobs. Thank you.

    • @umbral_studios
      @umbral_studios  ปีที่แล้ว +1

      You can actually use the same attribute sets on your mobs! If there are certain attributes that are specific to the player (and not mobs), I would suggest moving those into a separate attribute set. You would then give your player both attribute sets, and give your mobs the attribute set containing only the attributes they need. Does that make sense?

    • @MemberBenefit
      @MemberBenefit ปีที่แล้ว

      @@umbral_studios Thanks! Sounds good. Will try to make it this way. I'm still diving into GAS and I will need some time to sort the things out. I always try to find out an optimal architecture approach, we'll see if I can :)

  • @logicalcuber9171
    @logicalcuber9171 11 หลายเดือนก่อน

    Hi there!
    Can you give me a hint, how to get your gas to enhanced input setup multiplayer ready? I can't bind the abiltyspec on the client while using SetInputBinding!
    You would help me a lot😱

    • @logicalcuber9171
      @logicalcuber9171 10 หลายเดือนก่อน

      Ok, for everyone who has the same multiplayer problem ... Execute Give Ability function in an RunOnServer Event, then pass the SpecHandle into a RunOnOwningClient event, from there SetInputBinding function and pay Attention that the InputComponent is referenced before everthing. I´ve played with very high latency a bit and make definitly sure, that you check on the client if the gameplay object (GetGameplayAbilityFromSpecHandle) is valid, when not delay a bit and check again!

  • @adacer
    @adacer ปีที่แล้ว

    In my case, the ability is not called on the client. Is that intended or am I missing something?

    • @kingrb2555
      @kingrb2555 10 หลายเดือนก่อน

      You might forget to set the AbilitySystemComponent->SetIsReplicated(true)