20250211-WIL 언리얼 Move관련 오류

초보 게임개발자·2025년 2월 11일
0

UnrealEngine

목록 보기
9/18

이번 한 주 동안 언리얼에서 C++로 Pawn클래스 를 생성해서 WSAD와 마우스등을 사용해서 움직이는 액터를 만들어봤는데 AddMovementInput()를 사용하지않고
직접 움직이는 코드를 작성해서 해야 하다보니깐 여러가지 에러를 겪으면서 쉽지 않은 한 주를 보냈습니다.


겪은 에러 상황

  1. 코드를 다 작성해 보고 언리얼에서 실행시켜 보니 카메라 회전은 잘 되지만 움직일 생각조차 하지 않는 무심한 캐릭터

  2. 드디어 해결하고 잘 움직이는 듯싶었으나 방향이 바뀌는 순간 카트라이더 아이템을 맞은 것처럼 앞뒤 좌우 키가 서로 바뀌어서 움직이는 캐릭터

우선 첫번째 상황은 AddActorLocalOffset 에서 충돌 감지를 활성화 시켜주는 bSweep를 true로 설정했을 때 발생했는데요 결론은 캐릭터 기본 시작 위치를 불러오는 코드랑 설정해둔 Sweep이랑 무슨 충돌이 생겼는지 이동자체가 차단이 되어버려서 키를 입력해도 움직이지 않는걸 확인했습니다.

찾아보니깐 bsweep = true를 사용하면, 충돌이 발생하면 이동이 차단되거나, 보이지 않는 충돌 때문에 이동이 멈출수 있다고 합니다.

그리고 여러가지 방법들을 찾아보다가 몇가지 해결책을 발견을 해서 적어봅니다.

그전에 아래 함수에 대해서 간략하게 설명을 하고 가겠습니다.

AddActorLocalOffset()

  • AddActorLocalOffset()은 언리얼 엔진에서 액터(Actor)의 로컬 좌표(Local Space) 기준으로 위치를 변경하는 함수이며,
    이동 시 충돌 감지(Sweep)를 활성화할 수도 있으며, FHitResult를 활용해 충돌 정보를 받을 수도 있습니다.

기본 사용방법은 아래 처럼 사용하면서 필요한 부분들을 적어서 사용해주시면 됩니다.

AddActorLocalOffset(FVector DeltaLocation, bool bSweep = false, FHitResult* OutSweepHitResult = nullptr);

매개 변수 타입 설명
DeltaLocation / FVector / 이동할 거리(로컬 좌표 기준)
bSweep / bool / 충돌 감지를 활성화 할지 여부(true = 충돌감지)
OutSweepHitResult/ FHiResult* / 충돌이 발생했을 경우 충돌 정보를 저장(기본값 nullptr)

Sweep(충돌감지)란?

bsweep = true를 설정하면?

  • 이동경로를 따라 충돌을 검사함
  • 이동 도중 충돌이 감지되면, 충돌이 일어난 지점에서 멈추고 더 이상 이동하지 않음.
  • 충돌 정보를 FHitResult로 받을 수 있음

bsweep = false를 설정하면?

  • 충돌을 무시하고 이동함.
  • 벽이나 다른 오브젝트를 뚫고 지나갈 수 있음.

찾은 해결방법으로는
우선 첫 번째는 아예 bSweep 기능을 false를 두고 꺼버리는 거였습니다.

AddActorLocalOffset(DeltaLocation, false);

  • 이 경우 큰 무리없이 움직였습니다.

두 번째는 bSweep충돌 감지를 키고 사용 하고 싶을 때인데요

언리얼에서 만들어둔 Pawn블루프린터에서 CapsuleComp에 SimulatePhysics를 활성화 시켜준다음 PlayerStat 위치 값을 0,0,0 이 아닌 위로 시작하게 만들어 주면 왜 인지 캐릭터가 위에서 떨어지면서 충돌을 피했는지 정삭적으로 키를 입력했을 때 잘 움직이는걸 확인했습니다.
(이 부분은 실행 해보지는 않았지만 위와 같은 맥락이라면
C++에서 CapsuleComp->SetRelativeLocation(FVector(0, 0, 50)); ) 에서 위치조정을 해주면 캡슐이 지면과 겹치면서 이동이 멈출수있는 걸 방지해줘서
잘 작동이 되지 않을까 갑자기 생각이 나서 적어봅니다.

세 번째는 코드상에서 HitResult를 활용해서 충돌이 발생한 경우 디버깅할 수 있게 해줬습니다.


특정 오브젝트(예를들어서 문, 특정 트리거 액터등)과의 충돌만 무시하고 이동할 수 있도록 해줬으며, "PassThrough"태그를 가진 오브젝트는 충돌이 발생해도 그냥 이동하게 만들어 줬습니다.


두번째 오류는 위 오류를 해결하고 나서 발견했는데요 카메라 가 반대로 회전하는 순간 wsad 가 서로 바뀌는 현상이 발생했습니다.
이유를 찾아보니 코드에서 Local이랑 World축 이 혼합으로 사용이 되서 오류가 발생한것으로 확인했습니다.

  1. 첫번쨰 해결방법은

    AddActorLocalOffset 을 World로 변경해서 World축 기준으로 움직을수 있게 설정해줬습니다

이번에 알게된 사실인데

GetActorForwardVector, GetActorRightVector 가 world space 기반이라는 사실을 처음 알았습니다!.

그래서 Local을 world로 변경해서 실행 시켜 주니깐 잘 실행이 되는걸 확인 할 수 있었습니다.

그 다음 방법은 Local로 사용 하려고 할 때 인데

AddActorLocalOffset(FVector(MoveInput.X, MoveInput.Y, 0.f));

이렇게 코드를 작성하고 쓰면 MoveInput.X-> 캐릭터의 x축(정면 방향)이동, MoveInput.Y->캐릭터의 Y축(오른쪽 방향)이동, 0.f(Z축 상하이동 없음) 이라는 의미로
캐릭터의 로컬 방향을 기준으로 이동하게 됩니다.

그래서 방향을 더 명확하게 제어해주기 위해서 GetActorForwardVector()와-> 캐릭터가 바라보는 정면방향 GetActorRightVector()를-> 캐릭터의 오른쪽 방향 같이 활용하는것이 좋다고 하며 MoveInput.X와 MoveInput.Y를 각각 곱해주면 캐릭터의 회전 방향에 맞춰 이동할 수 있다고 합니다.

FVector MoveDirection = (GetActorForwardVector() * MoveInput.X) + (GetActorRightVector() * MoveInput.Y);
float MoveSpeed = 500.0f;
FVector DeltaLocation = MoveDirection.GetSafeNormal() * MoveSpeed * DeltaTime;
AddActorLocalOffset(DeltaLocation, true);

이번주 동안 저를 괴롭혔던 두 함수의 차이를 알아보고 마치겠습니다.

AddActorLocalOffset()과 AddActorWorldOffset()의 차이

두 함수에 가장 명확한 차이는 좌표기준,적용방식 에 있다고 생각합니다.

  • AddActorLocalOffset()의 경우는 로컬좌표(LocalSpace)기준이고 액터의 현재 방향을 기준으로 이동
    액터의 로컬 기준으로 100만큼 이동 (캐릭터가 회전하면 방향도 변함)
    AddActorLocalOffset(FVector(100.0f, 0.0f, 0.0f));
    AddActorLocalOffset()을 사용하면, 캐릭터의 바라보는 방향이 바뀌어도 로컬 기준으로 이동 방향이 유지됨.
  • AddActorWorldOffset()의 경우는 월드좌표(Worldspace)기준이고 절대 좌표 기준으로 이동 하는 차이가 있습니다.
    월드 기준으로 100만큼 이동 (캐릭터 회전에 관계없이 X축 방향으로 이동)
    AddActorWorldOffset(FVector(100.0f, 0.0f, 0.0f));
    반면 AddActorWorldOffset()을 사용하면, 캐릭터가 회전해도 이동 방향이 변하지 않음 (항상 월드 기준 X축으로 이동).

결론은
1. AddActorLocalOffset()은 기본적으로 로컬 좌표(Local Space) 기준으로 이동.
2. AddActorWorldOffset()을 사용하면 월드 좌표(World Space) 기준으로 이동.
3. FVector(MoveInput.X, MoveInput.Y, 0.f)을 AddActorLocalOffset()에 넣으면, 자동으로 캐릭터 기준으로 이동 방향이 설정됨.
4. GetActorForwardVector()와 GetActorRightVector()를 활용하면 회전 방향을 고려한 더 자연스러운 이동이 가능.


의식에 흐름데로 생각나는데로 글을 쓰다보니 잘 정리해서 쓴것 같지는 않지만 그래도 많이 배웠다는걸 알려드리고 싶었습니다.
이번 한 주 동안 캐릭터클래스가 아닌 액터클래스를 이용해서 움직일수 있게 C++로 구현을 해봤는데 처음에는 배운데로 하면 금방 하겠네 했다가 여러가지 에러를 겪고 그 과정에서 막히고 해결하고 를 반복하다보니깐 너무 힘들고 막막했었는데 이것저것 찾아보고 물어보고 하다 보니깐 자연스럽게 더 많은걸 알게되고 공부할수 있었던 계기가 되었던거 같습니다. * 이번을 계기로 다시한번 코드를 짤때 생각을 잘 하고 짜야겠다 다짐했고 local, world 축 이동 관련해서는 다시는 안 잊어버릴거 같습니다.

profile
기록은 기억을 지배한다!

0개의 댓글

관련 채용 정보