본문 바로가기

Day45/C++UE/트러블슈팅(Troubleshooting)

@lambone2025. 7. 22. 21:03

TIL(Today I Learned) [2025-07-22]

 

< 오늘 한 일 >

1. 코드카타

[관련 프로그램]

GitHub, BaekjoonHub

 

[내용]

- 문자열 나누기

 

2. 발제 과제 진행

[관련 프로그램]
Visual Studio 2022

Unreal Engine 5.5

 

[내용]

과제 진행 중

발제8 - 게임 루프 및 UI 재설계하기

 

4. Git 특강

[관련 프로그램]

Zoom

 

[내용]

GitLFS 사용법 익히기, 여러 가지 주의사항

2025.07.22 - [본캠프/Note Live] - Live/17/GitLFS

 

Live/17/GitLFS

일시 : [2025-07-22] 화요일 (14:00 - 15:50)학습 기록을 위하여 강의 수강 후 별도로 정리한 이하 내용에 대하여대부분의 참고 이미지, 개념 설명, 문제 풀이는 해당 강의 자료에서 발췌.또는 직접 실습

lambone.tistory.com

 

4. TA반 강의

[관련 프로그램]

Zoom

 

[내용]

머티리얼 실습 (디졸브) - 1

 

< 비고 >

- 라이브 세션

[2025-07-22] 화요일 (14:00 - 16:00) : Git LFS 특강

 

- 담당 튜터님 방문, 개인별 진행상황을 확인하셨다. 

- 회고, 트러블슈팅(Troubleshooting)

1. 에셋과 언리얼 버전 호환

사용하려는 에셋이 Unreal Engine 5.2 버전까지만 호환되기 때문에, 해당 버전을 별도로 설치한 후 어렵게 에셋을 가져와야 했다.

이번 과제에서는 이외에도 다양한 이슈들이 발생했으며, 같은 실수를 반복하지 않기 위해 기록으로 남기고 정리하게 되었다.

 

2. 리타기팅

그중 A 캐릭터의 스켈레탈 메시를 사용하고, B 캐릭터의 애니메이션 에셋을 적용해보려 했지만, 결과는 좋지 않았다.

A 캐릭터에 B 캐릭터의 애니메이션을 적용하자,

제대로 된 모션은커녕 캐릭터가 바닥에 박힌 채 누워 있거나 형태가 심하게 망가진 채 나타나는 문제가 발생했다.

이를 해결하기 위해 A와 B 각각의 스켈레탈 메시를 리타기팅(retargeting) 해야 한다는 정보를 확인하고 여러 방법을 시도했지만,

시간이 꽤 걸린 데 비해 기대했던 결과는 나오지 않았다.

리타기팅 설정을 바꿔가며 여러 차례 시도했지만 여전히 정상적으로 작동하지 않아, 결국 두 에셋 모두 포기하게 되었다.

이후에는 스켈레탈 메시와 그에 맞는 기본 애니메이션(Idle, 걷기, 달리기, 점프)이 포함된 단일 캐릭터 에셋을 찾는 데에도 시간이 꽤 소요됐다.

제대로 된 캐릭터 에셋 하나 구하는 일이 이렇게 어려울 줄은 정말 몰랐다.

 

3. 에셋 용량

게다가 환경 에셋도 Unreal Engine 5.2 버전에서 어렵게 가져오긴 했지만,
용량이 무려 20GB에 달할 정도로 지나치게 무거워 결국 사용을 포기해야 했다.

레벨을 여는 데만 몇 분이 소요되었고, 맵에 배치된 불필요한 액터들을 삭제해도 전체 용량과 성능 부담은 여전히 심각했다.

비록 실제 게임에는 활용하지 못했지만, 디테일이 살아 있는 대규모 환경을 직접 둘러보며 스크린샷을 남겨두었다.

캐릭터, 애니메이션, 환경 에셋 구성은 구현하려는 게임의 전체 기획 방향에 큰 영향을 주는 요소이기 때문에,

에셋부터 확실히 정리한 후  본격적으로 개발을 시작하려 했던 것이었는데, 예상보다 시간이 너무 많이 지체되고 말았다.

이제는 더 이상 미룰 수 없다. 본격적인 기능 구현에 집중할 때다.

 

4. 캐릭터 애니메이션

과제 로직 구현을 서둘러야 하는데,
캐릭터의 움직임과 애니메이션 적용 문제로 인해 이 문제 해결에만 많을 시간을 소모했다.

 

이전의 두 캐릭터 에셋(스켈레탈 메시용, 애니메이션용)에 대한 미련을 버리고,
완전히 새로운 두 캐릭터 에셋을 찾아 사용하기로 했다.
그중 A 캐릭터의 스켈레탈 메시를 사용하였고, Idle, Walk, Run 애니메이션은 정상적으로 적용되었다.
그러나 Jump와 Land 애니메이션에서는 캐릭터가 사라지는 문제가 발생했다.

결국 A 캐릭터의 Jump와 Land 애니메이션을 사용하지 않고,
다른 B 캐릭터의 해당 애니메이션을 가져와 적용해 본 결과 정상적으로 동작하여 이를 사용하기로 결정했다.
다만 Jump 관련 스테이트 머신 로직이 기존과 달라, 이 부분을 수정하는 데에도 시간이 소요되었다.

또한, Idle, Walk, Run 애니메이션을 블렌드 스페이스로 구성하는 과정에서도 문제가 발생했다.
블렌드 스페이스에서는 캐릭터의 Velocity와 Direction 값을 기준으로 다음과 같이 애니메이션을 세팅했다.
- Velocity가 0인 경우: Idle
- Velocity가 600인 경우: Walk
- Velocity가 1200인 경우: Run

Direction 값은 -180에서 180 범위로, 다음과 같은 의미를 갖도록 설정했다:
- Direction이 90에 가까울수록: 캐릭터가 정면을 바라보며 오른쪽으로 움직이는 동작
- Direction이 -90에 가까울수록: 캐릭터가 정면을 바라보며 왼쪽으로 움직이는 동작
- Direction이 180 또는 -180에 가까울수록: 캐릭터가 정면을 바라보며 뒤로 움직이는 동작

하지만 이 블렌드 스페이스 설정은 월드상의 X축 +방향을 바라보고 움직일 때만 의도대로 작동했다.
그 외 방향에서는 애니메이션이 완전히 꼬여버렸다.

월드 X축 -방향을 바라보는 경우,
W키 입력 시 뒤로 걷기 애니메이션이 나왔고,
S키 입력 시 앞으로 걷는 애니메이션이 재생되는 증,
키 입력과 애니메이션이 반대로 동작했다.
A와 D 키 역시 좌우가 서로 뒤바뀌어 재생되었다.

월드 Y축의 +방향과 -방향에서도 비슷한 문제가 나타났으며,
W/S 키 입력 시 A/D 방향 애니메이션이 재생되거나,
A/D 키 입력 시 W/S 방향 애니메이션이 나오는 등
의도와 다르게 움직였다.

여러 방법을 시도해 봤지만,
결국 캐릭터가 정면을 유지한 채 좌우 또는 뒤로 걷는 애니메이션 연출은 포기하고,
카메라 방향을 기준으로 캐릭터의 이동 방향을 계산하는 방식으로 로직을 전환했다.

 

5. 캐릭터 Move 로직 변경

기존 수업 예제의 Move 함수는 캐릭터가 바라보는 방향을 기준으로 앞/뒤, 좌/우를 계산했으며,
이 방식이 문제의 원인이 되기도 했다.

결국 일반적인 TPS/FPS, RPG, 어드벤처 게임처럼
플레이어가 바라보는 카메라 방향을 기준으로 캐릭터가 이동하도록 구현을 변경했다.

그리고 Control Rig를 구현하도록 시도하였으나 현재의 에셋으로 적용하는 방법을 모르겠어서 그냥 두기로 했다.

이 과정에서 수많은 설정 변경과 테스트를 반복하며 문제를 해결해 나갔고,
그 흔적들은 아래에 정리해 두었다.

 

- 블렌드 스페이스 적용 내용

 

- 이벤트그래프

 

- 애님 그래프 (Locomotion 내부, 블렌드스페이스 적용 관련 시행착오)

 

- 애님 그래프 (MainStates 내부, Jump/Land 적용 관련 시행착오)

AS-IS (기존)

 

TO-BE (개선)

 

- 캐릭터 세팅 (블루프린트)

 

- C++ (캐릭터 생성자)

// 생성자나 BeginPlay에서 세팅

// 캐릭터가 컨트롤러의 Yaw 회전을 따라가지 않도록 설정
// -> 이동 방향을 기준으로 캐릭터가 회전하게 하려면 false여야 함
bUseControllerRotationYaw = false;

// 캐릭터가 이동 방향을 기준으로 자연스럽게 회전하도록 설정
// -> 예: 앞으로 이동하면 캐릭터가 자동으로 앞을 보게 됨
GetCharacterMovement()->bOrientRotationToMovement = true;

// 캐릭터가 회전할 때의 속도를 설정 (Pitch, Yaw, Roll 순서)
// 이동 방향 전환 시 부드럽지만 빠르게 회전하는 느낌을 줌
// 아래 예시는 Yaw(좌우 회전)만 설정하여 초당 420도 속도로 회전하도록 함
// ex) GetCharacterMovement()->RotationRate = FRotator(0.f, 420.f, 0.f); // 초당 420도 Yaw 회전
// -> 블루프린트에서 직접 수정

 

- C++ (캐릭터 Move)

void ATRACharacter::Move(const FInputActionValue& value)
{
	/*
		기준: 캐릭터 방향
		캐릭터가 바라보는 방향을 기준으로 앞/뒤, 좌/우를 판단
		
		만약 카메라가 캐릭터 뒤에 고정되어 있고
		캐릭터가 그쪽을 바라보는 형태라면, 입력 방향과 이동 방향이 일치.
		
		하지만 카메라가 자유롭게 회전하거나 조작자가 보는 방향으로 이동하기 원한다면
		직관적이지 않을 수 있다.
	*/
	//if (!Controller) return;

	//const FVector2D MoveInput = value.Get<FVector2D>();
	//if (!FMath::IsNearlyZero(MoveInput.X))
	//{
	//	AddMovementInput(GetActorForwardVector(), MoveInput.X);
	//}
	//if (!FMath::IsNearlyZero(MoveInput.Y))
	//{
	//	AddMovementInput(GetActorRightVector(), MoveInput.Y);
	//}

	/*
		기준: 카메라 회전(Yaw)
		Controller->GetControlRotation().Yaw: 일반적으로 카메라의 회전(Yaw)을 의미
		따라서 이 방식은 카메라가 바라보는 방향을 기준으로 이동 방향을 계산
		예를 들어, 카메라가 오른쪽을 바라보면 W 키(앞)는 캐릭터가 오른쪽으로 움직인다.
		이는 대부분의 3인칭 액션 게임, 어드벤처 게임 등에서 기대하는 이동 방식

		유저가 보는 방향을 기준으로 캐릭터가 움직이는 것이 더 직관적이고 조작감이 좋다.
		특히 자유 카메라가 있는 3인칭 게임에서는, 카메라 회전과 별개로 캐릭터가 고정된 방향으로 움직이면 불편하다.
		예) 유저가 왼쪽을 보고 있는데 W키 누르면 캐릭터는 "자기 기준 앞"으로 가버려서, 화면 기준으로는 엉뚱한 방향으로 이동
	*/
	if (!Controller) return;

	const FVector2D MoveInput = value.Get<FVector2D>();
	const FRotator YawRotation(0, Controller->GetControlRotation().Yaw, 0); // Yaw만 사용
	const FVector ForwardDir = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	const FVector RightDir = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

	if (!FMath::IsNearlyZero(MoveInput.X))
	{
		AddMovementInput(ForwardDir, MoveInput.X);
	}
	if (!FMath::IsNearlyZero(MoveInput.Y))
	{
		AddMovementInput(RightDir, MoveInput.Y);
	}
}

 

'TIL (Today I Learned)' 카테고리의 다른 글

Day47/C++UE/커리어데이  (0) 2025.07.24
Day46/C++UE/과제(8)해설  (2) 2025.07.23
Day44/C++UE  (0) 2025.07.21
Day43/C++UE  (0) 2025.07.18
Day42/C++UE  (1) 2025.07.17
lambone
@lambone :: Unreal Storage

Unreal 학습 기록

"거인의 어깨 위에 올라서라"

목차