
지금까지는 에디터에서 플레이 버튼을 누르면 자동으로 서버에 접속되는 방식이었다. 하지만 실제 배포될 게임은 '타이틀 화면'에서 IP를 입력하고 접속하는 과정이 필수적이다.
오늘은 타이틀 전용 레벨과 게임모드를 별도로 제작하여 수동으로 서버에 접속하는 기능을 구현하고, 레벨이 바뀔 때 필수적으로 처리해야 하는 입력 모드(Input Mode) 전환 이슈를 해결했다.
OpenLevel 함수를 사용한 IP 직접 접속(Direct Connection) 구현타이틀 화면은 캐릭터가 총을 쏘는 게임 월드가 아니다. 따라서 인게임용 GameMode를 그대로 쓰면 불필요한 캐릭터가 스폰되거나 HUD가 뜨는 문제가 생긴다.
따라서 타이틀 전용 가벼운 GameMode를 따로 만들어야 한다.
DefaultPawn을 None으로 설정 (캐릭터 스폰 방지).BeginPlay에서 바로 로그인 위젯을 띄우고, 마우스 커서를 보이게 설정(bShowMouseCursor = true).클라이언트가 특정 서버로 이동하는 함수는 UGameplayStatics::OpenLevel이다. 여기에 접속하려는 IP 주소를 넣으면 엔진이 해당 서버로 여행(Travel)을 떠난다.
💡 Network Tip:
- 127.0.0.1 (Localhost): 혼자 테스트할 때는 자신의 컴퓨터를 가리키는 루프백 주소인
127.0.0.1을 입력하면 된다.- Port 7777: IP 뒤에 별도 포트를 적지 않으면 언리얼 기본 포트인
:7777로 접속을 시도한다.
// [DXTitlePlayerController.cpp]
void ADXTitlePlayerController::JoinServer(const FString& InIPAddress)
{
if (InIPAddress.IsEmpty()) return;
// 입력받은 IP 주소를 이름(FName)으로 변환
FName NextLevelName = FName(*InIPAddress);
// 해당 주소로 레벨 이동 (Absolute = true 옵션으로 IP 접속)
UGameplayStatics::OpenLevel(GetWorld(), NextLevelName, true);
}
플레이어가 OpenLevel을 통해 서버에 도착하면, 서버의 GameMode에서는 PostLogin 함수가 호출된다.
이 시점은 "플레이어의 전송이 완료되고, 서버에 온전한 PlayerController가 생성된 직후"이다.
가장 많이 하는 실수 중 하나다. 타이틀에서는 마우스를 쓰기 위해 UIOnly 모드를 썼는데, 게임 레벨로 넘어가서도 이 모드가 유지되어 캐릭터가 움직이지 않는 버그가 발생했다. ⚠️
레벨이 바뀌면 반드시 입력 모드를 게임용으로 초기화해줘야 한다.
// [DXPlayerController.cpp] - 게임용 컨트롤러
void ADXPlayerController::BeginPlay()
{
Super::BeginPlay();
// 로컬 플레이어(내 화면)인 경우에만 입력 모드 설정
if (IsLocalController())
{
// 다시 게임 조작 모드로 변경 (마우스 숨김, 키보드 이동 가능)
FInputModeGameOnly GameOnlyMode;
SetInputMode(GameOnlyMode);
}
}
| 개념 | 설명 | 주의 사항 |
|---|---|---|
| Title GameMode | 타이틀 전용 규칙 | DefaultPawn을 None으로 설정할 것 |
| OpenLevel | IP 주소로 서버 접속 | 스팀/콘솔 친구 초대는 Session 방식 사용 |
| PostLogin | 접속 완료 이벤트 | GameMode에서 관리하며, 접속 직후 1회 실행됨 |
| Input Mode | 입력 방식 결정 | 레벨 이동 시 UIOnly GameOnly 전환 필수 |