Let's talk

RSExampleCharacter.cpp

Examples/RSExampleCharacter.cpp Raw Download ZIP

Click a line number to link it. Shift-click to select a range.

1// Copyright (c) 2026 Reignance Studios. MIT License, see LICENSE.
2
3#include "RSExampleCharacter.h"
4
5#include "AbilitySystemComponent.h"
6#include "Abilities/GameplayAbility.h"
7#include "GameFramework/PlayerState.h"
8#include "RSAbilitySystemLibrary.h"
9
10UAbilitySystemComponent* ARSExampleCharacter::GetAbilitySystemComponent() const
11{
12 // Ask the PlayerState, never FindAbilitySystemComponent(this): that checks this
13 // actor's IAbilitySystemInterface first, which is this function, and recurses.
14 return URSAbilitySystemLibrary::FindAbilitySystemComponent(GetPlayerState());
15}
16
17void ARSExampleCharacter::PossessedBy(AController* NewController)
18{
19 Super::PossessedBy(NewController);
20
21 InitAbilityActorInfo();
22 GrantStartupAbilities();
23}
24
25void ARSExampleCharacter::OnRep_PlayerState()
26{
27 Super::OnRep_PlayerState();
28
29 // Without this, the owning client's ASC has no avatar: predicted abilities
30 // fail to activate locally, and montages and cues play only on the server.
31 InitAbilityActorInfo();
32}
33
34void ARSExampleCharacter::InitAbilityActorInfo()
35{
36 APlayerState* PS = GetPlayerState();
37 UAbilitySystemComponent* ASC = PS ? URSAbilitySystemLibrary::FindAbilitySystemComponent(PS) : nullptr;
38 if (!ASC)
39 {
40 return;
41 }
42
43 // Owner = PlayerState (holds the ASC), Avatar = this pawn (plays montages, has a location).
44 ASC->InitAbilityActorInfo(PS, this);
45}
46
47void ARSExampleCharacter::GrantStartupAbilities()
48{
49 UAbilitySystemComponent* ASC = GetAbilitySystemComponent();
50 if (!ASC || !HasAuthority())
51 {
52 return;
53 }
54
55 // Grant once per PlayerState, not once per pawn. Respawned pawns reuse the
56 // same ASC, so granting again would stack duplicate specs.
57 for (const TSubclassOf<UGameplayAbility>& AbilityClass : StartupAbilities)
58 {
59 if (AbilityClass && !ASC->FindAbilitySpecFromClass(AbilityClass))
60 {
61 ASC->GiveAbility(FGameplayAbilitySpec(AbilityClass, 1, INDEX_NONE, this));
62 }
63 }
64}

Still desyncing in packaged builds?

Free code fixes one symptom. A Diagnostic finds the cause across your project in two days.