Customizing 시 InputMode 변경하기

김여울·2025년 12월 16일

내일배움캠프

목록 보기
129/139

오늘 고쳐야 했던 문제들

1) 이미 장착돼 있던 첫 번째 아이템 + 새로 클릭한 아이템에 체크마크가 동시에 남는다
2) InputMode를 변경해서 커스터마이징 할 때도 캐릭터가 이동 가능하게 한다

체크 중복 표시 문제

1번 문제는 UI 선택 상태 관리가 슬롯 단위로 정리되지 않았다고 생각해서

  • LoadPartCategory() 시작 시 선택 상태 초기화
  • 자동 선택 전에 기존 선택 해제 (안전장치)

했지만 안됐다..

두 번째 조치로

  • 서버 쪽에서 SetCharacterPart에서 제거 복제 보장
    • SetCharacterPart()에서 RemoveCurrent()가 일어난 루프마다 Dirty 처리
  • UI 쪽에서 “슬롯당 1개 선택”을 Map이 아니라 그리드 전체를 스캔해서 강제
    • 클릭할 때는 무조건 그 슬롯의 다른 애들을 다 끄기
    • voidClearSelectionForSlot(ECharacterPartSlot PartSlot, UPartItemWidget* Except = nullptr);
    • HandlePartItemClicked에서 강제 정리
SlotToSelectedItem.Remove(PartSlot);
ClearSelectionForSlot(PartSlot,nullptr);

세 번째 조치로
캐릭터의 디폴트 파츠 상태 ALNCharacter::InitCharacter() 에서 디폴트 파츠를 SetCharacterPart() 로 여러 번 세팅하는 구조이기 때문에

  • 기존 장착 파츠”가 UI 기준으로는 하나가 아니라여러 개로 인식되는 상태가 만들어짐
    → 그 상태에서 새 파츠를 클릭하니까 기존 + 새 파츠가 동시에 체크되는 현상

  • InitCharacter에서는 기존 파츠를 전부 비운 뒤 디폴트 파츠를 한 번만 세팅하기

voidALNCharacter::InitCharacter()
{
if (!CharacterData)return;

// 기존 파츠 전부 제거
if (CharacterPartComponent)
	{
		CharacterPartComponent->ClearAllCharacterParts();
	}

if (auto CharacterAppearanceData = CharacterData->AppearanceData.Find(
		LNCharacterTags::CharacterData_Appearance_Default))
	{
for (auto CharacterPart : CharacterAppearanceData->SkeletalMeshes)
		{
			CharacterPartComponent->SetCharacterPart(CharacterPart);
		}
	}
}

이렇게 다 했는데 안돼서 일단 기준님과 해결하기로 했다...

캐릭터가 안 움직이던 문제

2번 문제 CustomizeWidget에서 아무리 InputMode를 바꿔도 안됐는데
PlayerController Client_OpenCustomizeUI_Implementation() 함수에서 FInputModeUIOnly로 설정하고 있어서 막혔었다.

cppvoid ALNControllerInGame::Client_OpenCustomizeUI_Implementation()
{
    if (!IsValid(CustomizeMenuClass)) return;
    
    if (CustomizeWidget == nullptr)
    {
       CustomizeWidget = CreateWidget(this, CustomizeMenuClass);
    }

    if (CustomizeWidget && !CustomizeWidget->IsInViewport())
    {
       CustomizeWidget->AddToViewport();

       // FInputModeUIOnly를 FInputModeGameAndUI로 변경하여 캐릭터 이동을 허용
       FInputModeGameAndUI InputMode;
       InputMode.SetWidgetToFocus(CustomizeWidget->TakeWidget()); // 위젯에 포커스 주기
       InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); // 마우스를 잠그지 않기
       InputMode.SetHideCursorDuringCapture(false); // 마우스 커서를 캡처 중에도 보이게 하기
       SetInputMode(InputMode);

       bShowMouseCursor = true; // 마우스 커서를 표시하기
    }
}

void ALNControllerInGame::Client_CloseCustomizeUI_Implementation()
{
    if (CustomizeWidget && CustomizeWidget->IsInViewport())
    {
       CustomizeWidget->RemoveFromParent();
    }

    // 위젯이 닫힐 때 게임 전용 입력 모드로 복구
    FInputModeGameOnly InputMode;
    SetInputMode(InputMode);
    bShowMouseCursor = false; // 마우스 커서를 숨기기
}

저번에 UIManageSubsystem에서 SetInputModeGameAndUI 함수 만들어놨으니까 그걸로 대체하기

cpp#include "UI/Subsystem/LNUIManageSubsystem.h" 


void ALNControllerInGame::Client_OpenCustomizeUI_Implementation()
{
    if (!IsValid(CustomizeMenuClass)) return;
    
    if (CustomizeWidget == nullptr)
    {
       CustomizeWidget = CreateWidget(this, CustomizeMenuClass);
    }

    if (CustomizeWidget && !CustomizeWidget->IsInViewport())
    {
       CustomizeWidget->AddToViewport();

       // UIManageSubsystem의 SetInputModeGameAndUI 함수를 호출 -> 게임과 UI 동시 입력을 허용
       if (ULNUIManageSubsystem* UISubsystem = GetGameInstance()->GetSubsystem<ULNUIManageSubsystem>())
       {
          UISubsystem->SetInputModeGameAndUI(this, CustomizeWidget, true, false);
       }
    }
}

void ALNControllerInGame::Client_CloseCustomizeUI_Implementation()
{
    if (CustomizeWidget && CustomizeWidget->IsInViewport())
    {
       CustomizeWidget->RemoveFromParent();
    }

    // UIManageSubsystem의 SetInputModeGameOnly 함수를 호출 -> 게임 전용 입력 모드로 복구
    if (ULNUIManageSubsystem* UISubsystem = GetGameInstance()->GetSubsystem<ULNUIManageSubsystem>())
    {
       UISubsystem->SetInputModeGameOnly(this);
    }
}

2번 문제는 해결 완료 ~

0개의 댓글