본문 바로가기
프로그래밍/Unreal 부트캠프

TIL 2025.02.05 기록

by Rozentea 2025. 2. 5.

0. 개요


으럇챠! 오늘 과제를 다 마무리해서 제출까지 끝냈다..

감기가 아직도 낫질 않아서 저녁까지 밤새서 작업하지도 못해서 너무 아쉬웠다...

단순 과제더라도 최대한 완성도 있게, 게임 답게? 만들고 싶고, 내가 설정한 목표였는데, 건강 이슈로 원하는 만큼 결과물을 얻지 못한것 같아 아쉬웠다.

 

그래도 이번 과제는 너무너무 재미있었기 때문에 다음 과제도 기대되고, 즐겁게 작업할 수 있어서 좋았다. ㅎㅎ

 

오늘은 캐릭터와 드론에 Grab 기능 추가하기, Selectable 인터페이스를 만들어 상호작용 구현하기, 여러 상호작용 만들기..

정도를 빠르게 마치고, 영상을 빠르게 편집해 제출까지 마무리지었다.

 

그래도 어제 저녁에 맵 작업을 다 마무리해 뒀어서 시간내에 완성할 수 있었던 것 같다.

 

그러면 오늘도 과제에 대해서 쭉 정리하고, 다음주 과제를 위해서 강의를 들으러가야겠다.

 

그리고.. 오늘은 몸이 너무 안좋아져서... 칼퇴해야겠다.. ㅠ

감기만 다 나으면 바로 새벽까지 공부한당..! +ㅅ+

 

1. 과제


1. Grab 기능 추가하기

Grab 구현의 경우엔 충분히 직접 처음부터 끝까지 완성할 수 있지만, 그래도 이미 만들어져 있는 컴포넌트를 사용하는게 좋다고 생각되어 UPhysicsHandleComponent를 사용해 구현했다.

(음.. 캐릭터 무브먼트 안쓰고 이동, 충돌처리 등등 다 구현하려고 노력했고... 부족하긴 하지만 나왔으니까.. 이번엔 만들어진 컴포넌트를 쓰고 싶었던 이유가 더 컸던거 같다.. ㅋㅋㅋㅋㅋㅋ)

 

UPhysicsHandleComponent 는 피직스 오브젝트를 "잡아서" 이동시키면서 잡는 오브젝트가 피직스를 계속 사용할 수 있도록 하는 오브젝트이다. (오.. 문서를 보니 물체를 잡아 당기는 중력총 같은걸 구현할 때도 쓰인다 한다. 아..! 아마 투사체가 점점 주변을 당기는 그런 중력총이 아니라.. 게리모드나 포탈에 있는 그냥 물건 끌어당겨와서 총에 부착?시키는 그런 중력총인가 보당...)

아무튼 요지는! 피직스 시뮬레이션이 켜져있는 오브젝트에 한에서만 부착시킬 수 있다.

 

또 해당 Component는 SceneComponent를 상속받아 만들어진 컴포넌트가 아니기 때문에 SceneComponent들에 Attach 시킬 수 없다..

 

void ASpartaCharacter::Grab(const FInputActionValue& value)
{
	static bool ToggleGrabbing = false;
	if (value.Get<bool>())
	{
		if (!ToggleGrabbing)
		{
			FVector Start = GetActorLocation();
			FVector End = Start + GetActorForwardVector() * GrabLength;

			FHitResult HitResult;
			FCollisionQueryParams Params;
			Params.AddIgnoredActor(this);

			//DrawDebugLine(GetWorld(), Start, End, FColor::Red, false);
			if (GetWorld()->SweepSingleByChannel(HitResult,Start,End,FQuat::Identity,ECC_Pawn,FCollisionShape::MakeCapsule(35.0f, 47.0f),Params))
			{
				if (Cast<ISelectableInterface>(HitResult.GetActor()))
				{
					SELECTABLE_TYPE TargetType = Cast<ISelectableInterface>(HitResult.GetActor())->GetSelectableType();
					if ( TargetType == SELECTABLE_TYPE::GRAB)
					{
						PhysicsHandleComp->GrabComponentAtLocationWithRotation(HitResult.GetComponent(), NAME_None, HitResult.ImpactPoint, GetActorRotation());
						bIsGrabbing = true;
						ToggleGrabbing = true;
					}
					else if (TargetType == SELECTABLE_TYPE::GRAB_HOLDROT)
					{
						PhysicsHandleComp->GrabComponentAtLocationWithRotation(HitResult.GetComponent(), NAME_None, HitResult.ImpactPoint, HitResult.GetActor()->GetActorRotation());
						bIsGrabbing = true;
						ToggleGrabbing = true;
					}
				}
			}
		}
		else
		{
			PhysicsHandleComp->ReleaseComponent();
			ToggleGrabbing = false;
			bIsGrabbing = false;
		}
	}
}

 

Grab은 위처럼 키를 입력받아서 바인딩 된 Grab함수가 호출되면, SweepSingleByChannel()을 이용해 캐릭터의 정면에 피직스 핸들에 부착시킬 수 있는 물체가 있는지 확인하고, 있다면 피직스 핸들에 해당 물체를 붙여주는 방식으로 진행했다.

 

단순히 부착만 한다고해서 부착당한 액터가 움직이지는 않기 때문에 Tick()에서 해당 액터를 움직여주었다.

이땐, 피직스 핸들 컴포넌트에 있는 SetTargetLocationAndRotation()를 이용해 주었다.

 

부착한 물체를 떼어내는 즉, 해제하는 함수는 ReleaseComponent()이다.

 

조금 어색해보이는 이유는.. 이땐 코드 수정전이라.. 처음 누를 땐 동작하지 않는.. 이슈가 있을 때였다.. ㅋㅋㅋㅋ

영상을 다시 찍진 않아서.. 헿... 암튼 수정이 잘되어서 잘 동작한다. >ㅅ< b

생각보다 맛있게 나온 드론 Grab!

문제는 이렇게 드론에 기능을 추가해 실제로 사용해보니.. 드론 컨트롤을 자연스럽게 잘 만들지는 못했다는게 확 느껴졌었다.. ㅠㅠㅠㅠ

 

2. Selectable 인터페이스 만들기

플레이어가 선택해 상호작용을 해야할 오브젝트들이 특정 상호작용 행동을 할 수 있도록 해주는 인터페이스를 만들 필요성을 느껴 이렇게 진행했다.

또한, 인터페이스를 만들어 붙여주게되면, 대상 액터를 인터페이스로 Cast해볼 수 있기 때문에 이 액터가 상호작용이 가능한 액터인지 확인하기에도 용이하다.

 

또, 이번에 enum class를 언리얼에서 처음 사용해 봤는데, 사용법을 알고나니 c++과 크게 다르지도 않고 괜찮았다.

음.. 단순히 매크로를 추가해 주어서 리플렉션 시스템에 등록해 에디터에서 보여준다는 정도의 차이?

UENUM(BlueprintType)
enum class SELECTABLE_TYPE : uint8
{
	GRAB,
	GRAB_HOLDROT,
	ROTATE,
	BTN,

	END
};

UENUM(BlueprintType)
enum class EActionButtonType : uint8
{
	None UMETA(DisplayName = "None"),
	Spawn UMETA(DisplayName = "Spawn"),
	MoveActor UMETA(DisplayName = "MoveActor"),

	End
};

 

UENUM() 매크로를 통해 리플렉션 시스템에 등록해준다.

마찬가지로 지정자를 넣어줄 수 있다.

 

주의할 점은 enum class들은  : uint8을 반드시 붙여주어야 한다. (언리얼에서 지원하는게 uint8인 모양이었다.)

음.. 사용해본 결과 에디터에 노출할 필요가 없는 enum class의 경우 uint8, UENUM 등등이 다 필요없고 c++문법대로 작성하면 잘 동작한다.

=> 하지만 이러면 에디터에서 노출해 인스턴스 객체마다 다른 enum값을 지니게는 만들지 못한다.

=> 상황에따라 다르게 쓰면 될 것 같다.

 

또, enum 항목에다가 UMETA(DisplayName = "None") 를 붙여서 에디터에서 어떤 이름으로 표시할지를 따로 정해줄 수도 있다. (디폴트로 출력해주는 이름은 그냥 enum 항목 이름과 똑같다.)

 

인터페이스에 대한 내용은 이전에도 사용해본 내용이라.. 굳이 정리하진 않겠다.

(심지어 다음 강의가 인터페이스에 대한 내용이니까 그거까지 듣고 추가로 정리할게 있다면 정리해야겠다... 싶다.)

 

3. 상호작용 만들기

<오브젝트 회전 시키기>

이제 이걸로 레이저 퍼즐을 깰 수 있게되었다..!

조아조아..

 

<충돌이 발생하면 특정 행동하기>

버튼을 눌러서 액터도 소환하는 기능이 있고, 아니면 이미 생성되어 있는 액터에 명령을 내려주는 기능도 있다.

 

<물체 잡기>

이건 사실 1번 항목에서 만들었던 Grab에 조건을 추가한게 끝이기 때문에 영상은 스킵하겠다.

 

2. 과제 최종 영상


 

<6번 과제 : 회전 발판과 움직이는 장애물 퍼즐 스테이지>

 

 

<7번 과제 : Pawn 클래스로 3D 캐릭터 만들기>

 

3. 마무리


이렇게 1~2주간 과제를 마무리 할 수 있었다.

중간에 설날도 끼고, 감기도 걸리는 등 작업을 꾸준히 하지 못하고 이래저래 컨디션도 들쭉날쭉 했지만, 구상했던, 경험해보고 싶었던, 목표들을 모두 이루고 과제를 마칠 수 있어서 꽤 성공적이었다.

 

모델링 모드를 이용해 맵을 만드는 것도 미리 해봤고, 인터페이스도 잘 활용했고, 랜덤 스폰도 말이 되게 잘 만들고, 이전 플랫포머 게임을 만들 때 구현한 기능들을 다시 C++로 모두 만들어보고, 드론을 이용한 퍼즐 등등.. 이번 과제를 어떻게 해결해나가고, 어떤 공부들을 할지에 대한 계획은 모두 지켜졌다. ㅎㅎ

 

조금 더 완성도 있게 나올 수 있었을텐데.. 건강 이슈로 작업시간을 줄일 수 밖에 없어서 아쉬운점이 남긴한다.. ㅎㅎ

 

다음 과제는 UI, 웨이브 시스템, 나이아가라 등등인데, 다음 과제도 기대된다.

음.. 그치만 시간이 이번 과제보다 훨씬 적어서.. 아무래도 많이 빡쎄게 해야할 것 같다.

 

과제 구상은 어느정도 마쳐뒀는데, 음.. 우선 코인을 줍는 게임으로 만들어볼 생각이고, 리더 보드, 시작 UI, 장애물에 부딪히면 코인 떨어뜨리기(마리오 처럼), 나이아가라를 이용해 다양한 이펙트 만들기 등등이다.

음... 생각보다..? 이번 과제보다 할만 할 것 같다.

(이번꺼는... 캐릭터 무브먼트 못쓰고, 물리 시뮬레이션 못쓰는게 너무 컸다... ㅠㅠ 오히려 이전에 PhysX 이식해 사용하는 것보다 훨씬 훨씬... 빡쎘다... ;ㅅ;)

 

더보기
썸넬용.. ㅎㅎ

'프로그래밍 > Unreal 부트캠프' 카테고리의 다른 글

TIL 2025.02.10 기록  (0) 2025.02.10
TIL 2025.02.06 기록  (1) 2025.02.06
TIL 2025.02.04 기록  (0) 2025.02.04
TIL 2025.02.03 기록  (0) 2025.02.03
TIL 2025.01.31 기록  (0) 2025.01.31