unreal 8기

언리얼 팀 프로젝트(멀티플레이) - 제시어 도형으로만들고 맞추기(1)

왕건 2026. 6. 30. 21:03

Unreal 테스트 배치 시스템 구현 정리

오늘은 Unreal 프로젝트에서 테스트용 캐릭터 입력과 도형 배치 시스템의 기본 흐름을 구현했다.

목표는 플레이어가 도형을 선택하고, 화면 앞에 프리뷰를 띄운 뒤, 원하는 위치와 회전값으로 서버에 설치 요청을 보내는 구조를 만드는 것이었다.

1. 테스트 캐릭터 입력 구성

먼저 BP_TestCharacter가 사용할 테스트 Pawn 기반 C++ 클래스를 구성했다.

추가한 기본 구성은 다음과 같다.

  • CapsuleComponent
  • MeshComponent
  • SpringArmComponent
  • CameraComponent
  • FloatingPawnMovement
  • Enhanced Input용 MappingContext
  • MoveAction
  • MoveUpAction
  • LookAction

이동 입력은 클라이언트에서 바로 반응하도록 처리했고, 동시에 서버에도 RPC로 이동 요청을 보내도록 만들었다.

서버에서는 위치를 직접 갱신하고 SetReplicateMovement(true)를 통해 다른 클라이언트에도 위치가 보이도록 했다.

2. Shape DataTable Row 추가

도형 정보를 DataTable로 관리하기 위해 FShapeDefinitionRow를 만들었다.

USTRUCT(BlueprintType)
struct TEAMPROJECT_API FShapeDefinitionRow : public FTableRowBase
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Shape")
	TObjectPtr<UStaticMesh> Mesh;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Shape")
	TObjectPtr<UMaterialInterface> PreviewMaterial;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Shape")
	TObjectPtr<UMaterialInterface> PlacedMaterial;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Shape")
	FVector DefaultScale = FVector::OneVector;
};

DataTable의 RowName은 Box, Sphere처럼 도형 ID로 사용했다.

각 Row에는 Mesh, PreviewMaterial, PlacedMaterial, DefaultScale을 등록했다.

이렇게 해두면 코드에서는 RowName만으로 어떤 도형을 설치할지 결정할 수 있다.

3. Placement Preview Actor 구현

설치 전 미리보기를 담당하는 APlacementPreviewActor를 만들었다.

이 Actor는 클라이언트에서만 보이는 프리뷰용 Actor다.

SetPreviewShape() 함수에서는 DataTable Row를 찾아 Static Mesh, Preview Material, Default Scale을 적용한다.

프리뷰 Actor는 서버에 복제하지 않는다.

프리뷰는 설치 전에 현재 플레이어만 보는 임시 표시이기 때문에 서버에 올릴 필요가 없다.

4. 실제 설치 Actor 구현

실제로 설치되는 도형은 APlacedShapeActor로 만들었다.

이 Actor는 서버에서 Spawn되고 다른 클라이언트에도 보여야 하므로 복제를 켰다.

bReplicates = true;
SetReplicateMovement(true);

또한 Mesh, Material, Scale이 다른 클라이언트에서도 제대로 적용되도록 복제 필드를 추가했다.

서버에서 도형을 Spawn한 뒤 DataTable Row를 읽어 Mesh와 Material을 적용하고, 그 값이 클라이언트로 복제되도록 구성했다.

5. PlayerController에서 배치 흐름 구현

ATestPlayerController에 도형 배치 흐름을 구현했다.

현재 입력은 다음과 같다.

  • 1: Box 프리뷰 시작
  • 2: Sphere 프리뷰 시작
  • 마우스 휠 위: 프리뷰를 시점 방향으로 더 멀리 이동
  • 마우스 휠 아래: 프리뷰를 플레이어 쪽으로 이동
  • Q: 누르고 있는 동안 반시계 방향 회전
  • E: 누르고 있는 동안 시계 방향 회전
  • 좌클릭: 현재 프리뷰 위치와 회전으로 서버에 설치 요청

프리뷰 위치는 Tick()에서 계속 갱신한다.

플레이어 시점에서 앞으로 LineTrace를 쏘고, 맞은 지점이 있으면 그 위치에 프리뷰를 둔다.

맞은 지점이 없으면 현재 설정된 PreviewDistance만큼 앞에 프리뷰를 둔다.

6. 프리뷰 거리 조절

마우스 휠로 프리뷰 거리를 조절할 수 있게 했다.

기본값은 다음과 같다.

PreviewDistance = 600.0f;
MinPreviewDistance = 150.0f;
MaxPreviewDistance = 2000.0f;
PreviewDistanceStep = 100.0f;

마우스 휠을 올리면 PreviewDistance가 증가해서 프리뷰가 더 멀어진다.

마우스 휠을 내리면 PreviewDistance가 감소해서 프리뷰가 플레이어 쪽으로 가까워진다.

설치할 때는 현재 프리뷰 Actor의 Transform을 그대로 서버에 보내기 때문에, 조절한 거리 그대로 설치된다.

7. 프리뷰 회전 처리

처음에는 Q/E를 누를 때마다 한 번씩 회전하도록 만들었다.

하지만 사용성이 좋지 않아서, 키를 누르고 있는 동안 계속 회전하도록 수정했다.

현재는 PreviewYaw 값을 PlayerController가 가지고 있고, Q/E 입력 상태를 bool로 저장한다.

bool bIsRotatingCounterClockwise;
bool bIsRotatingClockwise;

그리고 Tick()에서 DeltaTime 기준으로 회전값을 계속 누적한다.

PreviewYaw = FRotator::NormalizeAxis(
	PreviewYaw + (RotationDirection * PreviewRotationStep * DeltaTime)
);

이 방식은 프레임레이트에 크게 의존하지 않고 부드럽게 회전할 수 있다.

기본 회전 속도는 초당 90도다.

PreviewRotationStep = 90.0f;

8. 서버 Spawn 구조

좌클릭하면 클라이언트는 현재 프리뷰의 Transform을 서버 RPC로 보낸다.

Server_RequestSpawnShape(CurrentPreviewShapeId, PreviewActor->GetActorTransform());

서버에서는 다시 DataTable Row를 찾아 검증한다.

검증이 끝나면 실제 설치 Actor를 Spawn한다.

APlacedShapeActor* PlacedShape = World->SpawnActor<APlacedShapeActor>(
	PlacedShapeActorClass,
	SpawnTransform,
	SpawnParameters
);

Spawn 이후에는 SetPlacedShape()를 호출해서 Mesh, Material, Scale을 적용한다.

이렇게 하면 클라이언트가 프리뷰로 본 위치와 회전 그대로 서버에 설치되고, 다른 클라이언트에도 복제된다.

9. 전체 흐름 정리

현재 배치 시스템 흐름은 다음과 같다.

  1. 1 또는 2 키 입력
  2. ShapeId 선택
  3. DataTable에서 Mesh / Material / Scale 조회
  4. PreviewActor 생성
  5. PreviewActor에 Mesh / PreviewMaterial / Scale 적용
  6. Tick()에서 프리뷰 위치 갱신
  7. 마우스 휠로 프리뷰 거리 조절
  8. Q/E로 프리뷰 회전 조절
  9. 좌클릭
  10. PreviewActor의 Transform을 서버 RPC로 전송
  11. 서버에서 DataTable Row 재검증
  12. 실제 Shape Actor Spawn
  13. Mesh / Material / Scale 적용
  14. 다른 클라이언트에 복제

10. 오늘 구현하면서 정리한 점

프리뷰는 클라이언트에서만 보여도 된다.

하지만 실제 설치 결과는 반드시 서버에서 처리해야 한다.

클라이언트가 직접 Actor를 Spawn하면 자기 화면에서는 보일 수 있지만, 서버나 다른 클라이언트 기준에서는 제대로 반영되지 않는다.

그래서 최종 설치는 서버 RPC를 통해 처리했다.

또한 설치 위치와 회전은 클라이언트가 보고 있는 프리뷰 Transform을 서버로 보내는 방식으로 처리했다.

다만 서버에서는 DataTable Row를 다시 확인해서 유효한 ShapeId인지 검증한다.

11. 다음에 할 일

다음 단계에서는 프리뷰 단계에서 색상 팔레트를 선택할 수 있게 만들 예정이다.

예상 구조는 다음과 같다.

  1. 도형 선택
  2. 프리뷰 생성
  3. 팔레트에서 색상 선택
  4. 프리뷰 색상 변경
  5. 좌클릭 설치
  6. 서버 RPC로 ShapeId / Transform / SelectedColor 전송
  7. 서버에서 검증 후 실제 Actor Spawn
  8. 선택한 색상 적용

프리뷰 색상 변경은 클라이언트에서만 처리해도 된다.

하지만 최종 설치 색상은 게임 결과에 영향을 주기 때문에 서버로 보내야 한다.

12. 남은 고민

현재 테스트 캐릭터는 APawn + UFloatingPawnMovement 기반으로 만들었다.

테스트 단계에서는 충분하지만, 실제 플레이어 이동까지 생각하면 나중에는 ACharacter + CharacterMovementComponent 기반으로 정리하는 것이 더 안정적일 수 있다.

특히 멀티플레이 환경에서는 CharacterMovementComponent가 네트워크 예측과 보정을 기본적으로 지원하기 때문에 장기적으로는 더 적합하다.

이번 작업은 배치 시스템의 기본 흐름을 빠르게 검증하기 위한 테스트 구현이라고 보면 된다.

'unreal 8기' 카테고리의 다른 글

2026-6-23 TIL  (0) 2026.06.23
2026-6-22 TIL  (0) 2026.06.22
2026-6-19 TIL  (0) 2026.06.19
2026-6-18 TIL  (0) 2026.06.19
2026-6-17 TIL  (0) 2026.06.17