#I know there are a couple of older posts
1 messages · Page 1 of 1 (latest)
Figure a thread might be easier to follow with multiple conversations going @mellow shard
AAstralPlayerState::AAstralPlayerState(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
AbilitySystemComponent = ObjectInitializer.CreateDefaultSubobject<UAstralAbilitySystemComponent>(this, TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Full); //Unless we enable multiplayer full replication is the best bet
StatsSet = CreateDefaultSubobject<UDefaultAttributeSet>(TEXT("StatsSet"));
}
what's AstralPlayerState.h line 45?
whats AbilitySystemComponent in header
The core implementation here is very similar to Lyra, if not the exact same in many cases.
Oh my mistake, I'll grab the header
Line 45 is:
// Gets the ability system component used for game wide things
UFUNCTION(BlueprintCallable, Category = "Astral|PlayerState")
UAstralAbilitySystemComponent* GetAstralAbilitySystemComponent() const { return AbilitySystemComponent; }
seems loke UAstralPawnExtensionComponent::HandleChangeInitState is trying to call GetAstralAbilitySystemComponent on a nullptr
so the UAstralAbilitySystemComponent you store and use there is invalid?
run with debugger attached to crash and go up in callstack
how AbilitySystemComponent uprop declared as?
UPROPERTY(VisibleAnywhere, Category = "Astral|PlayerState")
TObjectPtr<UAstralAbilitySystemComponent> AbilitySystemComponent;
then your problem somewhere is missing check in AstralPawnExtensionComponent.cpp:280
it's crashing in the get, so I can only assume that the this at that point is invalid
so this
I'll see if I can backtrack in the debugger 👍
just switch frames in call stack
in case you don't know how to debug, check this https://tackytortoise.github.io/2022/06/24/common-slacker-issues.html#basic-debugging
That's a great resource, I don't use the debugger very often so I'm not super well verse with all its tools.
another person who likes to suffer
Sure do, that's the game dev way!
in short, select DebugGame Editor configuration and press f5 to launch
when the crash occurs your IDE will break and you get all the info
So based on the debugger it looks like GetAstralAbilitySystemComponent() is null, so when HandleChangeInitState() tries to reference it, it breaks.
The ASC, however, should exist -- or at least I'd think it does considering I can interact with it in editor before PIE.
Is there an easy way to see where the ASC may have been changed to become null after PIE begins within the debugger?
show code of HandleChangeInitState
Sorry for the ignorance, what does "in handle" mean?
HandleChangeInitState
Probably not much help but here ya go
void UAstralPawnExtensionComponent::HandleChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState)
{
if (DesiredState == AstralGameplayTags::InitState_DataInitialized)
{
// This is currently all handled by other components listening to this state change
}
InitializeAbilitySystem(GetPlayerState<AAstralPlayerState>()->GetAstralAbilitySystemComponent(),GetPlayerState<AAstralPlayerState>());
}
oh. you do not check for null
if (CurrentState == LyraGameplayTags::InitState_DataAvailable && DesiredState == LyraGameplayTags::InitState_DataInitialized)
APawn* Pawn = GetPawn<APawn>();
ALyraPlayerState* LyraPS = GetPlayerState<ALyraPlayerState>();
if (!ensure(Pawn && LyraPS))
{
return;
}
also you do the thing outside of state check
meaning it may be called at any state and not only when available/initialized
void ULyraHeroComponent::HandleChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState)
{
if (CurrentState == LyraGameplayTags::InitState_DataAvailable && DesiredState == LyraGameplayTags::InitState_DataInitialized)
{
APawn* Pawn = GetPawn<APawn>();
ALyraPlayerState* LyraPS = GetPlayerState<ALyraPlayerState>();
if (!ensure(Pawn && LyraPS))
{
return;
}
const ULyraPawnData* PawnData = nullptr;
if (ULyraPawnExtensionComponent* PawnExtComp = ULyraPawnExtensionComponent::FindPawnExtensionComponent(Pawn))
{
PawnData = PawnExtComp->GetPawnData<ULyraPawnData>();
// The player state holds the persistent data for this player (state that persists across deaths and multiple pawns).
// The ability system component and attribute sets live on the player state.
PawnExtComp->InitializeAbilitySystem(LyraPS->GetLyraAbilitySystemComponent(), LyraPS);
}
if (ALyraPlayerController* LyraPC = GetController<ALyraPlayerController>())
{
if (Pawn->InputComponent != nullptr)
{
InitializePlayerInput(Pawn->InputComponent);
}
}
// Hook up the delegate for all pawns, in case we spectate later
if (PawnData)
{
if (ULyraCameraComponent* CameraComponent = ULyraCameraComponent::FindCameraComponent(Pawn))
{
CameraComponent->DetermineCameraModeDelegate.BindUObject(this, &ThisClass::DetermineCameraMode);
}
}
}
}
That's a different script though, the Hero component and the Extension component.
Also my implementation (naming aside) is the same
//(I just called it CharacterGameplayComponent rather than "hero")
void UAstralCharacterGameplayComponent::HandleChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState)
{
if (CurrentState == AstralGameplayTags::InitState_DataAvailable && DesiredState == AstralGameplayTags::InitState_DataInitialized)
{
APawn* Pawn = GetPawn<APawn>();
AAstralPlayerState* AstralPS = GetPlayerState<AAstralPlayerState>();
if (!ensure(Pawn && AstralPS))
{
return;
}
const UAstralPawnData* PawnData = nullptr;
if (UAstralPawnExtensionComponent* PawnExtComp = UAstralPawnExtensionComponent::FindPawnExtensionComponent(Pawn))
{
PawnData = PawnExtComp->GetPawnData<UAstralPawnData>();
// The player state holds the persistent data for this player (state that persists across deaths and multiple pawns).
// The ability system component and attribute sets live on the player state.
PawnExtComp->InitializeAbilitySystem(AstralPS->GetAstralAbilitySystemComponent(), AstralPS);
}
if (AAstralPlayerController* AstralPC = GetController<AAstralPlayerController>())
{
if (Pawn->InputComponent != nullptr)
{
InitializePlayerInput(Pawn->InputComponent);
}
}
// Hook up the delegate for all pawns, in case we spectate later
if (PawnData)
{
if (UAstralCameraComponent* CameraComponent = UAstralCameraComponent::FindCameraComponent(Pawn))
{
CameraComponent->DetermineCameraModeDelegate.BindUObject(this, &ThisClass::DetermineCameraMode);
}
}
}
}
wait, so what you have.
this #1245269803460067348 message
or #1245269803460067348 message
first is wrong - it does not check for PS or State
second is correct - it does check for State and PS
The implementation for each is the same, in my version and Lyra's. Now I change some of the other stuff in each of these classes, but these functions at least are identical.
Yeah helpful advice regardless, especially since I've unlocked the debugger (feels like an item upgrade)
Ah, it looks Lyra changed HandleChangeInitState to no longer call InitializeAbilitySystem. Not sure whether the GIT version or UE marketplace version is correct, but I'll try removing that line and see if it works