* 문제 : 호출스택 타고가면서 탐색
원인 : 게임모드가 null임 / 게임모드는 gameplaystatics사용해서 클라에서 얻어오는경우에만 서버에서 유효함
클라에서 null이 되버림
UCharacterClassInfo* UAuraAbilitySystemLibrary::GetCharacterClassInfo(const UObject* WorldContextObject)
{
//게임모드를 얻어오고
AAuraGameModeBase* AuraGameMode = Cast<AAuraGameModeBase>(UGameplayStatics::GetGameMode(WorldContextObject));
if (AuraGameMode == nullptr) return nullptr;
//게임모드에있는 클래스정보들에 대해
return AuraGameMode->CharacterClassInfo;
}
* 해결 : auraEmemy > beginplay에서
능력주는 부분을 서버일경우에만 실행되도록함
if(HasAuthority())
{
UAuraAbilitySystemLibrary::GiveStartupAbilities(this,AbilitySystemComponent);
}
if(HasAuthority())
{
InitializeDefaultAttributes();
}
* 문제 : 클라에서 데미지 위젯이 안나옴
* 원인 : 0번 idx의 pc == 서버의 pc
클라에서는 당연히 not valid임
void UAuraAttributeSet::ShowFloatingText(const FEffectProperties& Props, float Damage, bool bBlockedHit, bool bCriticalHit) const
{
//데미지위젯을 데미지받은 캐릭위에 뛰우기
if(Props.SourceCharacter!=Props.TargetCharacter) //자기자신은 제외
{
AAuraPlayerController* PC= Cast<AAuraPlayerController>(UGameplayStatics::GetPlayerController(Props.SourceCharacter,0));
if(PC)
{
PC->ShowDamageNumber(Damage,Props.TargetCharacter,bBlockedHit,bCriticalHit);
}
}
}
* 해결 : 해당 소스(클라인경우는 클라의 aura / 서버인경우 서버의 aura)의 pc를 받아오도록 수정.
void UAuraAttributeSet::ShowFloatingText(const FEffectProperties& Props, float Damage, bool bBlockedHit, bool bCriticalHit) const
{
//데미지위젯을 데미지받은 캐릭위에 뛰우기
if(Props.SourceCharacter!=Props.TargetCharacter) //자기자신은 제외
{
AAuraPlayerController* PC= Cast<AAuraPlayerController>(Props.SourceCharacter->Controller);
if(PC)
{
PC->ShowDamageNumber(Damage,Props.TargetCharacter,bBlockedHit,bCriticalHit);
}
}
}
IslocalController => 로컬(클라)에서만 데미지 띄우도록 수정
//대상 캐릭터위에 데미지 띄워주는 함수
//RPC함수 : 서버에서 호출가능
void AAuraPlayerController::ShowDamageNumber_Implementation(float DamageAmount, ACharacter* TargetCharacter, bool bBlockedHit, bool bCriticalHit)
{
//대상캐릭터위치에 위젯생성함
if(IsValid(TargetCharacter) && DamageTextComponentClass && IsLocalController())
{
UDamageTextComponent* DamageText= NewObject<UDamageTextComponent>(TargetCharacter, DamageTextComponentClass);
DamageText->RegisterComponent(); //위젯을 동적생성 -> 수동으로 컴포넌트 등록
//Text를 대상캐릭터의 루트에 붙이기
DamageText->AttachToComponent(TargetCharacter->GetRootComponent(),FAttachmentTransformRules::KeepRelativeTransform);
DamageText->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); //계속못따라다니도록 분리, 그냥 사라질숫자임
DamageText->SetDamageText(DamageAmount, bBlockedHit,bCriticalHit); //Text값 설정
}
}
* 문제 : 클라모드로실행 -> 전용서버생김 -> 전용서버에서는 아무것도 안나옴
구현 : 각자 클라에서는 각자의 데미지만 표시
* 원인 : targetASC에서
void AAuraProjectile::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
//오버랩되면 소리재생
UGameplayStatics::PlaySoundAtLocation(this,ImpactSound,GetActorLocation(),FRotator::ZeroRotator);
//오버랩되면 효과실행
UNiagaraFunctionLibrary::SpawnSystemAtLocation(this,ImpactEffect,GetActorLocation());
//클라에서 사운드 파괴된경우 예외처리
if(LoopingSoundComponent) LoopingSoundComponent->Stop();
// LoopingSoundComponent->Stop(); // 적과오버랩되면 불 자체에서나는 루핑사운드 중지
//서버에있는경우
if(HasAuthority())
{
if(auto TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(OtherActor))
{
//GE 적용하기
TargetASC->ApplyGameplayEffectSpecToSelf(*DamageEffectSpecHandle.Data.Get());
}
Destroy(); //파괴 => 클라에복제안되게
}
* 해결 : 예를들어, 불 발사자가 클라1이고 내가 클라 2인경우, 클라2에서는 효과발생자가 클라1 != 나(클라2) 이므로
do nothing 처리.
void AAuraProjectile::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
//효과발생자 == 다른액터(클라)인경우 do nothing ()
if(DamageEffectSpecHandle.Data.Get()->GetContext().GetEffectCauser() == OtherActor) return;
null check 추가
//효과발생자 == 다른액터인경우 do nothing ()
if(DamageEffectSpecHandle.Data.IsValid() && DamageEffectSpecHandle.Data.Get()->GetContext().GetEffectCauser() == OtherActor) return;
* 문제 : 불이 적 머리위로 지나감
* 해결 : pitch 0 삭제
void UAuraProjectileSpell::SpawnProjectile(const FVector& ProjectileTargetLocation)
{
//GEngine->AddOnScreenDebugMessage(1,8.f,FColor::Blue,FString("Effect Applied!"));
//발사체는 서버에서생성, 클라는 복제본을 보게될거임
//발사체가 서버에있는지 어케암?
const bool bIsServer = GetAvatarActorFromActorInfo()->HasAuthority(); //아바타액텨 ==불 의 권위확인
if(! bIsServer) return ; //발사체가 서버있는경우만 발사체 생성
ICombatInterface* CombatInterface = Cast<ICombatInterface>(GetAvatarActorFromActorInfo()); //해당액터가 전투인터를 구현하면, 얻을수있음
if(CombatInterface)
{
const FVector SocketLocation = CombatInterface->GetCombatSocketLocation();
FRotator Rotation = (ProjectileTargetLocation - SocketLocation).Rotation(); //방향벡터의 회전각 구하기
// Rotation.Pitch=0.f; // 지면과 평행하게 움직이도록
* 자잘한 버그 fix
- 클라에서 소리가2번나는 버그 해결 : !bHit인경우에만 실행 되도록 수정
void AAuraProjectile::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
//효과발생자 == 다른액터(클라)인경우 do nothing ()
if(DamageEffectSpecHandle.Data.IsValid() && DamageEffectSpecHandle.Data.Get()->GetContext().GetEffectCauser() == OtherActor) return;
if(!bHit)
{
//오버랩되면 소리재생
UGameplayStatics::PlaySoundAtLocation(this,ImpactSound,GetActorLocation(),FRotator::ZeroRotator);
//오버랩되면 효과실행
UNiagaraFunctionLibrary::SpawnSystemAtLocation(this,ImpactEffect,GetActorLocation());
//클라에서 사운드 파괴된경우 예외처리
if(LoopingSoundComponent) LoopingSoundComponent->Stop();
// LoopingSoundComponent->Stop(); // 적과오버랩되면 불 자체에서나는 루핑사운드 중지
}
'UE5 > Advance Damage Techniques' 카테고리의 다른 글
[UE5] Advanced Damage 기술 퀴즈 (0) | 2024.08.22 |
---|---|
[UE5] 방마저에따른 데미지 감소 구현 (0) | 2024.08.22 |
[UE5] 방마저 속성추가 / 리플리케이션 / 속성위젯에 속성추가 (0) | 2024.08.18 |
[UE5] 데미지 유형들 추가, 확장성 refactor (0) | 2024.08.15 |
[UE5] 크리시 글자 애니메이션 구현, 메시지 구현, 인스턴싱 정책 (0) | 2024.08.14 |