TIL: Unreal C++ 트러블슈팅 46일차

박춘팔·2026년 6월 8일

언리얼 TIL

목록 보기
44/61

누적 학습 시간 : 490시간 34분

📅 2026-06-08

CH3 개인과제

PIE 컨트롤러 조작 관련 트러블슈팅

증상

Rider에서 Shift + F10으로 언리얼 에디터를 실행한 직후, 에디터에서 첫 번째 PIE를 시작하면 플레이어 입력이 동작하지 않는다.

동작하지 않는 입력은 다음과 같다.

  • 키보드 이동 입력
  • 마우스 회전 입력

하지만 첫 PIE를 ESC로 종료한 뒤 다시 PIE를 실행하면 입력이 정상 동작한다.

정리하면 재현 순서는 다음과 같다.

  1. Rider에서 Shift + F10 실행
  2. Unreal Editor 열림
  3. 첫 PIE 실행
  4. 마우스 회전 및 키보드 입력 미동작
  5. ESC로 PIE 종료
  6. PIE 재실행
  7. 입력 정상 동작

현재 입력 구조

APlayerCharacter에서 Enhanced Input을 사용한다.

  • UInputAction을 C++ 생성자에서 CreateDefaultSubobject로 생성
  • UInputMappingContext도 C++ 생성자에서 생성
  • WASD, Mouse2D, Space, Shift, V 키를 C++에서 매핑
  • BeginPlay()에서 UEnhancedInputLocalPlayerSubsystem::AddMappingContext() 호출
  • SetupPlayerInputComponent()에서 각 InputAction을 바인딩

관련 파일:

  • Source/MS_Simulator/Public/PlayerCharacter.h
  • Source/MS_Simulator/Private/PlayerCharacter.cpp
  • Config/DefaultInput.ini
  • Config/DefaultEngine.ini

프로젝트 설정상 Enhanced Input 기본 클래스는 설정되어 있었다.

DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent

이미 시도했고 실패한 조치

아래 조치들은 모두 문제를 해결하지 못했으며, 테스트 후 원상복구했다.

1. HUD 위젯 포커스 비활성화

가설:

첫 PIE에서 HUD 위젯이 입력 포커스를 가져가서 캐릭터 입력이 막힐 수 있다.

시도:

  • HUDWidget->SetVisibility(ESlateVisibility::HitTestInvisible);
  • HUDWidget->SetIsFocusable(false);

결과:

  • 해결되지 않음

2. 다음 틱에서 강제로 게임 입력 모드 복구

가설:

첫 PIE 시작 직후 Viewport 또는 Widget 포커스가 늦게 잡혀서 입력 모드가 꼬일 수 있다.

시도:

  • GetWorldTimerManager().SetTimerForNextTick(...)
  • FInputModeGameOnly
  • PlayerController->SetInputMode(InputMode)
  • PlayerController->SetShowMouseCursor(false)
  • SetIgnoreMoveInput(false)
  • SetIgnoreLookInput(false)

결과:

  • RestoreGameInputFocus() 관련 코드 원복 완료

3. 입력 매핑 등록 위치를 BeginPlay()에서 SetupPlayerInputComponent()로 이동

가설:

첫 PIE에서 BeginPlay() 시점에는 입력 컴포넌트나 LocalPlayer Subsystem 준비가 덜 되었을 수 있다.

시도:

  • BeginPlay()AddMappingContext() 제거
  • SetupPlayerInputComponent()에서 바인딩 직전 AddMappingContext() 호출

결과:

  • 변경 원복 완료

4. AutoPossessPlayer = EAutoReceiveInput::Player0 추가

가설:

첫 PIE에서 캐릭터가 Player0에게 자동 소유되지 않아 입력을 받지 못할 수 있다.

시도:

  • APlayerCharacter 생성자에 AutoPossessPlayer = EAutoReceiveInput::Player0; 추가

결과:

  • 변경 원복 완료

5. NotifyControllerChanged()에서 입력 매핑 등록

가설:

Possession 타이밍이 BeginPlay()보다 늦게 발생해서, 컨트롤러가 붙은 뒤에 매핑해야 할 수 있다.

시도:

  • NotifyControllerChanged() override 추가
  • 컨트롤러 변경 시 AddMappingContext() 호출
  • BeginPlay()AddMappingContext() 제거

결과:

  • 변경 원복 완료

6. HUD 생성 자체 임시 비활성화

가설:

첫 PIE에서 생성되는 HUD가 직접 입력을 막고 있을 수 있다.

시도:

  • BeginPlay()CreateWidget
  • AddToViewport
  • Presenter 바인딩 블록 임시 비활성화

결과:

  • 변경 원복 완료

현재까지 확인된 사실

  • HUD 위젯 포커스 문제일 가능성은 낮다.
  • 단순한 InputModeGameOnly 복구로는 해결되지 않는다.
  • BeginPlay, SetupPlayerInputComponent, NotifyControllerChanged 사이의 단순 타이밍 문제만으로 보기 어렵다.
  • 캐릭터의 단순 Auto Possess 설정만으로는 해결되지 않는다.
  • 두 번째 PIE부터는 정상 동작하므로 코드 자체의 입력 바인딩 로직이 완전히 틀린 상태는 아니다.

다음에 우선 확인할 후보

1. C++ 생성자에서 InputAction과 MappingContext를 동적으로 만드는 구조

현재 UInputActionUInputMappingContext를 에셋이 아니라 C++ 생성자에서 CreateDefaultSubobject로 만들고 있다.

특히 UInputMappingContext::MapKey()NewObject<UInputModifier...>()를 생성자에서 직접 호출한다.

첫 에디터 실행 직후 첫 PIE에서만 입력이 안 먹고, 두 번째 PIE부터 정상화되는 증상은 에셋 로딩이나 CDO 초기화 순서 문제와도 맞닿아 있을 수 있다.

다음 시도 후보:

  • IA_Move, IA_Look, IA_Jump, IA_Sprint, IA_TogglePerspective, IMC_Player를 Content Browser 에셋으로 생성
  • APlayerCharacter에는 UPROPERTY(EditDefaultsOnly) 참조만 둠
  • BP_PlayerCharacter에서 해당 에셋들을 할당
  • C++ 생성자에서 MapKey() 호출 제거

2. 첫 PIE의 실제 Pawn, Controller, InputComponent 확인

두 번째 PIE부터 동작한다는 점 때문에, 첫 PIE에서 실제로 Possess되는 Pawn이 기대한 BP_PlayerCharacter인지 확인해야 한다.

확인 후보:

  • 첫 PIE에서 GetPawn()이 어떤 클래스인지
  • SetupPlayerInputComponent()가 호출되는지
  • PlayerInputComponentEnhancedInputComponent인지
  • GetController()가 유효한지
  • LocalPlayerEnhancedInputLocalPlayerSubsystem이 유효한지

단, 이미 단순 로그 추가만으로 해결되는 작업은 아니므로 다음에는 원인 확인용 로그를 더 구체적으로 설계해서 한 번에 봐야 한다.

3. GameMode와 BP 설정 확인

현재 Config/DefaultEngine.ini는 BP GameMode를 기본 GameMode로 사용한다.

GlobalDefaultGameMode=/Game/Gamemode/BP_MSSimulator_Gamemode.BP_MSSimulator_Gamemode_C

C++ AMSSimulatorGamemode는 현재 기본 Pawn이나 PlayerController 설정이 비어 있다.

다음 확인 후보:

  • BP_MSSimulator_Gamemode의 Default Pawn Class
  • BP_PlayerCharacter가 실제 기본 Pawn인지
  • TestLevel의 World Settings에서 GameMode Override가 있는지
  • 레벨에 배치된 Pawn이 있는지, 또는 GameMode가 Spawn하는지
  • 배치된 Pawn의 Auto Possess Player 설정

4. Editor Preference 또는 PIE Viewport 포커스 문제

코드 조치가 모두 실패했고, Rider 실행 직후 첫 PIE에서만 발생하므로 에디터/PIE Viewport 포커스 문제일 가능성도 남아 있다.

다음 확인 후보:

  • 첫 PIE 직후 Viewport를 마우스로 클릭하면 입력이 살아나는지
  • Play in Selected ViewportNew Editor Window PIE에서 차이가 있는지
  • Editor Preferences의 Play 관련 Mouse Control 설정
  • Rider에서 실행된 에디터와 직접 실행한 에디터의 차이

다음 트러블슈팅 제안

가장 유력한 다음 작업은 C++에서 InputAction과 MappingContext를 런타임처럼 구성하는 방식을 버리고, Enhanced Input 에셋 기반 구조로 옮기는 것이다.

권장 순서:

  1. Content Browser에서 InputAction 에셋과 InputMappingContext 에셋 생성
  2. 현재 C++ 생성자 안의 CreateDefaultSubobject<UInputAction>(), CreateDefaultSubobject<UInputMappingContext>(), MapKey() 제거
  3. APlayerCharacter에는 에셋 참조용 UPROPERTY(EditDefaultsOnly)만 유지
  4. BP_PlayerCharacter에서 에셋 할당
  5. 기존처럼 BeginPlay()에서 AddMappingContext() 호출
  6. 첫 PIE 재현 테스트

이 작업은 구조 변경이므로, 적용 전 현재 상태를 커밋하거나 별도 백업 지점을 만드는 것이 좋다.

메모

다음에 이 문제를 다시 이어서 볼 때는 아래 조치를 반복하지 말 것.

  • HUD 포커스 비활성화
  • 다음 틱 InputModeGameOnly 강제 적용
  • AddMappingContext()SetupPlayerInputComponent()로 이동
  • AutoPossessPlayer = Player0 추가
  • NotifyControllerChanged()에서 매핑 등록
  • HUD 생성 블록 비활성화

위 조치들은 모두 테스트상 실패했다.

profile
이것 저것 다해보는 삶

0개의 댓글