1. 서버에서 충돌처리하도록 구조 변경
1) 새 트레이스 채널 - TR_PlayerAttack
(1) Config폴더에서 DefaultEngine.ini 에서 채널 번호 확인
2) PlayerKnight.h에 스폰이펙트 처리할 함수 추가
..
UFUNCTION( BlueprintCallable, NetMulticast, Reliable )
void SpawnEffect_MultiCast( FVector loc );
void SpawnEffect_MultiCast_Implementation( FVector loc );
3) cpp
void APlayerKnight::BeginPlay()
{
Super::BeginPlay();
if ( HasAuthority() )
{
UCapsuleComponent* capsule = GetCapsuleComponent();
capsule->OnComponentBeginOverlap.AddDynamic( this, &APlayerKnight::OnPlayerBodyCollision );
mAttackCollision->OnComponentBeginOverlap.AddDynamic( this, &APlayerKnight::OnPlayerAttackCollision );
}
}
ㄴ 서버탈때만 충돌처리
void APlayerKnight::SpawnEffect_MultiCast_Implementation( FVector loc )
{
UParticleSystem* particle = LoadObject<UParticleSystem>( nullptr, L"/Script/Engine.ParticleSystem'/Game/ParagonAurora/FX/Particles/Abilities/Primary/FX/P_Aurora_Melee_SucessfulImpact.P_Aurora_Melee_SucessfulImpact'" );
UParticleSystemComponent* particleCp = UGameplayStatics::SpawnEmitterAtLocation( GetWorld(), particle, loc, GetActorRotation(), true );
}
void APlayerKnight::AttackBegin()
{
//mAttackCollision->SetCollisionEnabled( ECollisionEnabled::QueryAndPhysics );
FVector start = GetActorLocation() + GetActorForwardVector() * 50.f;
FVector end = start + GetActorForwardVector() * 400.f;
FCollisionQueryParams params;
params.AddIgnoredActor( this );
TArray<FHitResult> result;
bool collision = GetWorld()->SweepMultiByChannel( result, start, end,
FQuat::Identity, ECollisionChannel::ECC_GameTraceChannel4, FCollisionShape::MakeSphere( 50.f ), params );
// 디버그일때만 그린다.
#if ENABLE_DRAW_DEBUG
FColor drawColor = collision ? FColor::Red : FColor::Green ;
DrawDebugLine( GetWorld(), start, end, drawColor, false, 1.0, 0, 50.f );
#endif
// 충돌된 물체가 있다면
if ( collision )
{
// Ranged For
for ( const FHitResult& hit : result )
{
// 파티클 (이펙트) 출력
UParticleSystem* particle = LoadObject<UParticleSystem>( nullptr, L"/Script/Engine.ParticleSystem'/Game/ParagonAurora/FX/Particles/Abilities/Primary/FX/P_Aurora_Melee_SucessfulImpact.P_Aurora_Melee_SucessfulImpact'" );
FVector loc = hit.Location;
UParticleSystemComponent* particleCp = UGameplayStatics::SpawnEmitterAtLocation( GetWorld(), particle, loc, GetActorRotation(), true );
}
}
}
void APlayerKnight::AttackEnd()
{
//mAttackCollision->SetCollisionEnabled( ECollisionEnabled::NoCollision );
}
void APlayerKnight::OnPlayerAttackCollision( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult )
{
GEngine->AddOnScreenDebugMessage( 1, 10.f, FColor::Black, L"OnPlayerAttackCollision" );
SpawnEffect_MultiCast( OtherActor->GetActorLocation() );
}
ㄴ> 충돌감지를 하고 충돌이 된다면 후처리한다.
- 트레이스 채널을 이용해서 충돌을 처리한다. 트레이스 채널 -> 레이를 이용해서 충돌을 감지한다.
레이 -> 레이저
▶️FCollisionQueryParams : 충돌에 대한 설정을 할 수 있다. 충돌 태그, 충돌무시 (IgnoreComponents, IgnoreActors ..)
▶️Ranged For
result의 범위만큼만 for문을 반복한다.
for ( const FHitResult& hit : result )
▶️디버그 드로잉
디버그모드에서 공격영역을 그리기
DrawDebugLine( GetWorld(), start, end, drawColor, false, 1.0, 0, 50.f );
또는
ENGINE_API void DrawDebugCapsule(const UWorld* InWorld, FVector const& Center, float HalfHeight, float Radius, const FQuat& Rotation, FColor const& Color, bool bPersistentLines = false, float LifeTime = -1.f, uint8 DepthPriority = 0, float Thickness = 0);
ㄴ> 얘는 #include “DrawDebugHelpers.h”
#if ENABLE_DRAW_DEBUG
...
#endif
이렇게 묶어서 디버그모드에서만 출력되도록 처리
⭐⭐ 컬리전 관련 이론정리
▶️컬리전 정리
언리얼 컬리전 제작 3가지 방법
1. 스태틱 메시 에셋 : 스태틱메시 에셋에 콜리전 영역을 심는 방법.
스태틱 메시 컴포넌트에서 비주얼과 충돌이라는 두 가지 기능을 설정할 수 있어서 편리.
2. 기본 도형 (Primitive) 컴포넌트 : 구체, 박스, 캡슐 등의 기본 도형을 사용해 스태틱 메시와 별도로 충돌 영역을 지정.
스켈레탈 메시를 움직일 때 주로 사용.
3. 피직스 에셋 : 일반적으로 캐릭터 이동은 캡슐 컴포넌트를 사용해 처리한다. 하지만 특정 상황에서 캐릭터 관절이 흐느적 거리는 헝겊 인형(RagDoll) 효과를 구현할 때 이 피직스 에셋을 사용한다. 캐릭터 각 부위에 기본 도형으로 충돌 영역을 설정하고 이를 연결해 의 물리를 설정한다. 피직스 애셋은 스켈레탈 매시에만 사용할 수 있다.
▶️ 기본 컬리전 채널
- WorldStatic : 움직이지 않는 정적인 배경 액터에 사용하는 콜리전 채널이다. 주로 스태틱메시 액터에 있는 스태틱메시 컴포넌트에 사용한다.
- WorldDynamic : 움직이는 액터에 사용하는 콜리전 채널이다. 블루프린트에 속한 스태틱메시 컴포넌트에 사용한다.
- Pawn : 플레이어가 조종하는 물체에 주로 사용한다. 캐릭터의 충돌을 담당하는 캡슐 컴포넌트에 설정된다.
- Visibility : 배경 물체가 시각적으로 보이는지 탐지하는데 사용한다. 탐지에서 폰은 제외된다. 마우스로 물체를 선택하는 피킹(Picking) 기능을 구현할 때 사용한다.
- Camera : 카메라 설정을 위해 카메라와 목표물 간에 장애물이 있는지 탐지하는데 사용한다. 이전 GTA 방식으로 캐릭터를 조작할 때 장애물이 시야를 가리면 카메라를 장애물 앞으로 줌인하는 기능(SpringArm->bCollisionTest = true)이 있었다. 이때 사용하는 채널이 Camera 채널이다.
- PhysicsBody : 물리 시뮬레이션으로 움직이는 컴포넌트에 설정한다.
▶️ Collision Enabled 항목이다. 설정값은 다음과 같다.
- Query : 두 물체의 충돌 영역이 서로 겹치는지 테스트하는 설정. 충돌 영역의 겹침을 감지하는 것을 오버랩(Overlap) 이라고 부르며, 충돌 영역이 겹치면 관련 컴포넌트에 BeginOverlap 이벤트가 발생한다. 지정한 영역에 물체가 충돌하는지 탐지하는 레이캐스트(Raycast) 나 스윕(Sweep) 기능도 Query 에 속한다.
- Physics : 물리적인 시뮬레이션을 사용할 때 설정한다.
- Query and Physics : 위의 두 기능을 모두 사용하는 설정이다.
▶️ 레이캐스트(Raycast) 는 '보이지 않는 광선'을 쏘아 광선의 진행 방향에 충돌할 물체가 있는지를 검사하는 방식이다.
▶️스윕(Sweep) 은 움직임에 제한을 줄때 사용된다. 예를 들어, 플레이어가 이동 중 벽을 만나면 중간에 멈추도록 만들 때 스윕을 이용한다.
▶️Query and Physics 설정을 사용하면 모든 기능이 잘 동작하겠지만, 계산량이 많아지므로 각 액터마다 필요한 설정만 지정하는 것이 효율적이다. 콜리전 프리셋 Pawn 에는 Collision Enabled 항목에 Query and Physics 가 설정되어 있다. 그리고 Query 기능을 사용하는 경우 관련 이벤트가 발생하도록 Generates Overlap Events 옵션이 체크돼 있다.
▶️ 콜리전 채널이 상대방 컴포넌트의 콜리전 채널과 어떻게 반응할지 지정해야하는 옵션값.
- 무시 (Ignore) : 콜리전이 있어도 아무 충돌이 일어나지 않는다.
- 겹침 (Overlap) : 무시와 동일하게 물체가 뚫고 지나갈 수 있지만 이벤트를 발생시킨다.
- 블록 (Block) : 물체가 뚫고 지나가지 못하도록 막는다
콜리전 채널은 오브젝트 채널과 트레이스 채널로 나뉜다.
- 오브젝트 채널 : 콜리전 영역에 지정하는 콜리전 채널 (WorldStatic, WorldDynamic, Pawn, PhysicsBody, Vehicle, Destructible)
- 트레이스 채널 : 어떤 행동에 설정하는 콜리전 채널 (Visibility, Camera)
▶️SweepSingleByChannel() : 트레이스 채널을 사용해 물리적 충돌 여부를 가리는 함수.
SweepMutiByChannel()
언리얼 엔진은 총 32개의 콜리전 채널을 제공한다. 그 중 8개는 언리얼 엔진이 기본으로 사용하고, 여섯 개는 다른 용도로 사용하도록 예약되어 있다. 따라서 우리는 나머지 18개만 사용 가능하다.
트레이스 채널을 사용해 물리적 충돌 여부를 가리는 함수 중 하나로 SweepSingleByChannel 이 있다. 물리는 월드의 기능이므로 GetWorld( ) 함수를 사용해 월드에게 명령을 내려야 한다.
해당 함수는 기본 도형을 인자로 받은 후 시작 지점에서 끝 지점까지 쓸면서(Sweep) 해당 영역 내에 물리 판정이 일어났는지를 조사한다. 이 함수의 인자들은 다음과 같다.
- HitResult : 물리적 충돌이 탐지된 경우 관련된 정보를 담을 구조체
- Start : 탐색을 시작할 위치
- End : 탐색을 끝낼 위치
- Rot : 탐색에 사용할 도형의 회전
- TraceChannel : 물리 충돌 감지에 사용할 트레이스 채널 정보
- CollisionShape : 탐색에 사용할 기본 도형 정보. 구체, 캡슐, 박스를 사용한다.
- Params : 탐색 방법에 대한 설정 값을 모아둔 구조체
- ResponseParams : 탐색 반응을 설정하기 위한 구조체
▶️TakeDamage
액터 클래스 AActor 에는 4개의 인자를 갖고 있는 TakeDamage 라는 함수가 구현돼 있다.
- DamageAmount : 전달할 대미지의 세기
- DamageEvent : 대미지 종류
- EventInstigator : 공격 명령을 내린 가해자
- DamageCauser : 대미지 전달을 위해 사용한 도구
여기서 대미지를 가한 진정한 가해자는 폰이 아니라 폰에게 명령이 아닌 플레이어 컨트롤러로 취급하므로, EventInstigator 에는 폰이 아닌 컨트롤러의 정보를 보내줘야 한다.
'Unreal Engine5 > KDT 2024' 카테고리의 다른 글
[UE5 KDT2024] 27. 몬스터 폰 제작 (0) | 2025.03.11 |
---|---|
[UE5 KDT2024] 26. 서버에서 충돌처리 2 (0) | 2025.03.10 |
[UE5 KDT2024] 24. 충돌 2 (0) | 2025.03.08 |
[UE5 KDT2024] 23. 충돌 (0) | 2025.03.07 |
[UE5 KDT2024] 22. 열거형 애니메이션 동기화 (0) | 2025.03.06 |
댓글