정찰 땐 다 같이 맵을 둘러보다가 본게임이 시작되면 술래와 하이더가 각자 자리로 흩어져야 함
캐릭터는 이미 정찰 단계에서 스폰돼 다 같이 맵을 둘러보고 있음
본게임 시작하면서 이미 존재하는 캐릭터의 위치를 옮기는 것!
처음 스폰 위치를 역할별로 나누는 문제였다면 ChoosePlayerStart를 오버라이드해 스폰 지점 선택 로직을 바꾸면 됨
하지만 스폰은 이미 끝난 상태기 때문에 페이즈가 전환되는 한순간에 위치만 이동(텔레포트) 시켜야 함
PlayerStart 태그
APlayerStart는 원래 스폰 지점으로 쓰는 액터라 위치, 회전 정보를 갖고 있고 PlayerStartTag라는 이름표 필드도 기본으로 제공한다 -> 여기에 Tagger / Hider를 지정하면 됨
레벨에 PlayerStart를 술래 자리, 하이더 자리에 배치하고 각각의 Player Start Tag에 역할 이름을 입력
하이더는 여럿이므로 하이더용 PlayerStart를 서로 떨어뜨려 여러 개
배치할 땐 바닥에서 살짝 띄워, 텔레포트 후 캡슐이 바닥에 파묻히지 않게 함
텔레포트 로직은 StartInGame이 이미 무거워서 TeleportPlayersToStarts 헬퍼로 분리
하는 일은 두 단계
태그별 수집
레벨의 PlayerStart를 전부 훑어 태그에 따라 두 배열로 나눔
TArray<APlayerStart*> TaggerStarts;
TArray<APlayerStart*> HiderStarts;
// TActorIterator: 레벨에 배치된 특정 타입 액터를 전부 순회하는 엔진 제공 반복자
for (TActorIterator<APlayerStart> It(GetWorld()); It; ++It)
{
APlayerStart* Start = *It;
if (!Start) continue;
if (Start->PlayerStartTag == TEXT("Tagger")) TaggerStarts.Add(Start);
else if (Start->PlayerStartTag == TEXT("Hider")) HiderStarts.Add(Start);
}
배치
각 캐릭터를 역할에 맞는 배열에서 하나씩 꺼내 옮김
int32 TaggerIdx = 0;
int32 HiderIdx = 0;
for (APlayerState* PS : GameState->PlayerArray)
{
const AFDPlayerState* FDPS = Cast<AFDPlayerState>(PS);
if (!FDPS) continue;
APawn* Pawn = FDPS->GetPawn();
if (!Pawn) continue;
APlayerStart* Target = nullptr;
if (FDPS->RoleTag == EFDRole::Tagger && TaggerStarts.Num() > 0)
{
Target = TaggerStarts[TaggerIdx % TaggerStarts.Num()];
++TaggerIdx;
}
else if (FDPS->RoleTag == EFDRole::Hider && HiderStarts.Num() > 0)
{
Target = HiderStarts[HiderIdx % HiderStarts.Num()];
++HiderIdx;
}
if (!Target) continue;
Pawn->SetActorLocation(Target->GetActorLocation(), false);
Pawn->SetActorRotation(Target->GetActorRotation());
}
하이더는 여럿인데 하이더용 PlayerStart가 하나뿐이면 모두 같은 좌표로 텔레포트돼 서로 안에 끼임
그래서 하이더용 PlayerStart를 여러 개 두고 인덱스 % 자리수 연산으로 캐릭터를 번갈아 나눠 담음
자리가 캐릭터보다 적어도 % 덕에 순환하며 배치되고, 자리가 넉넉하면 겹침 없이 흩어진다
Sweep은 끄기
SetActorLocation의 두 번째 인자 Sweep은 "출발지에서 목적지까지 경로를 훑어, 뭔가에 막히면 거기서 멈춤"이다
걸어서 이동할 땐 벽을 뚫지 않게 해주는 유용한 옵션이지만 텔레포트는 경로 자체가 없는 순간이동이니까 Sweep을 켜면 출발지와 목적지 사이의 벽에 막혀 목적지에 도착하지 못함
텔레포트는 SetPhase보다 먼저
// 위치부터 잡고 나서 phase를 바꾼다
TeleportPlayersToStarts();
FDGameState->SetPhase(EMatchPhase::InGame);
순서가 반대면 게임 시작!을 본 직후에 몸이 뿅 순간이동하는 어색한 장면이 연출됨
상태 전환(phase)과 그에 딸린 연출(팝업)이 있을 때 실제 세계의 변화(위치 이동)를 연출보다 앞에 두는 것
서버가 SetActorLocation으로 폰을 옮기면 그 변화가 복제로 모든 클라이언트에 전파
'프로젝트 > Funny Or Die (멀티플레이 술래잡기 게임)' 카테고리의 다른 글
| 순위표 WBP 생성 (0) | 2026.07.18 |
|---|---|
| 하이더 생존 순위 만들기 (0) | 2026.07.18 |
| [트러블슈팅] 리슨 서버에서 클라이언트만 인벤토리 UI가 갱신되지 않음 (0) | 2026.07.17 |
| 타이머 UI 시스템 구축 (0) | 2026.07.17 |
| [트러블슈팅] EOS 세션 연동 (0) | 2026.07.15 |
