기존에는 건물을 설치하면 해당 건물이 차지하는 그리드 셀을 점유 처리하는 구조였는데, 파괴 기능을 구현하려면 단순히 Actor만 Destroy()하면 안 된다. 건물이 차지하고 있던 그리드 점유 정보도 같이 해제해야 한다.
1. 파괴 모드
StartDestroyMode()를 호출하면 기존 건설 모드가 켜져 있을 경우 먼저 건설 모드를 취소하고, 파괴 모드만 활성화한다.
이후 Tick을 켜서 매 프레임 화면 중앙 기준으로 파괴 대상을 갱신하도록 했다.
void UKOGridBuildComponent::StartDestroyMode()
{
if (bIsBuildMode)
{
CancelBuildMode();
}
bIsDestroyMode = true;
SetComponentTickEnabled(true);
UpdateDestroyTargetPreview();
}
2. 바라보는 위치의 건물 찾기
파괴 모드에서는 TraceFromScreenCenter()로 화면 중앙에서 라인트레이스를 쏜다.
맞은 위치를 그리드 좌표로 변환한 뒤, 해당 셀을 점유하고 있는 Actor를 GetOccupyingActorAt()으로 가져온다.
const FIntPoint HitGrid = GridSub->WorldToGridPosition(HitResult.ImpactPoint);
AActor* TargetActor = GridSub->GetOccupyingActorAt(HitGrid);
SetDestroyTargetActor(TargetActor);
건물의 실제 메시를 직접 찾는 게 아니라, 그리드 점유 정보 기준으로 건물을 찾기 때문에
여러 칸을 차지하는 건물도 그중 아무 셀이나 바라보면 같은 건물을 찾을 수 있다.
3. 파괴 대상 시각화
파괴할 건물을 사용자가 눈으로 확인할 수 있도록 DestroyTargetMaterial을 적용했다.
대상 Actor가 바뀌면 이전 대상의 머티리얼을 먼저 복구하고, 새 대상에게 파괴 대상 머티리얼을 적용한다. 이를 위해 원래 머티리얼을 DestroyTargetOriginalMaterials 배열에 저장해 둔다.
CurrentDestroyTargetActor = NewTargetActor;
ApplyDestroyTargetMaterial(NewTargetActor);
머티리얼을 바꾸기 전에 원래 머티리얼을 저장한다.
OriginalData.Materials.Add(MeshComponent->GetMaterial(Index));
MeshComponent->SetMaterial(Index, DestroyTargetMaterial);
파괴 모드를 취소하거나 대상이 바뀌면 저장해 둔 머티리얼을 다시 복구한다.
RestoreDestroyTargetMaterial();
CurrentDestroyTargetActor = nullptr;
DestroyTargetOriginalMaterials.Empty();
4. 실제 파괴 처리
RequestDestroy()에서는 현재 선택된 파괴 대상이 유효한지 먼저 검사한다.
그다음 GridSub->FreeAreaByActor(TargetBuilding)을 호출해서 해당 건물이 차지하던 그리드 셀을 해제한다. 점유 해제가 성공하면 대상 Actor를 Destroy()한다.
if (!GridSub->FreeAreaByActor(TargetBuilding))
{
UE_LOG(LogTemp, Warning, TEXT("[Destroy] 점유 해제 실패: %s"),
*TargetBuilding->GetName()
);
return;
}
ClearDestroyTargetActor();
TargetBuilding->Destroy();
5. 그리드 점유 해제 구조
건물을 설치할 때는 OccupyArea()에서 건물이 차지하는 모든 셀에 같은 Actor를 저장하고, OccupiedAreaByActor에도 Actor와 점유 영역 정보를 저장한다.
OccupiedArea.Anchor = AnchorLocation;
OccupiedArea.Size = AreaSize;
OccupiedAreaByActor.Add(OccupyingActor, OccupiedArea);
파괴할 때는 FreeAreaByActor()가 이 정보를 이용해서 해당 Actor가 차지하던 영역을 찾아낸다.
그 후 FreeArea()를 호출해 각 셀의 OccupyingActor를 비운다.
if (!OccupiedAreaByActor.RemoveAndCopyValue(OccupyingActor, OccupiedArea))
{
return false;
}
FreeArea(OccupiedArea.Anchor, OccupiedArea.Size);
정리
파괴 기능은 다음 역할을 한다.
- 파괴 모드 진입
- 화면 중앙 라인트레이스로 파괴 대상 탐색
- 그리드 점유 정보를 기준으로 대상 건물 찾기
- 대상 건물에 파괴 표시용 머티리얼 적용
- 클릭 시 점유 셀 해제
- Actor 삭제
- 머티리얼 복구 및 대상 초기화
'Unreal 최종 팀프로젝트' 카테고리의 다른 글
| [TIL] 건설 회전 기능 | 최종 팀프로젝트 (0) | 2026.06.02 |
|---|---|
| [TIL] UI 입력 흐름 | 최종 팀프로젝트 (0) | 2026.06.01 |
| [TIL] 설비 및 아이템 데이터화 | 최종 팀프로젝트 (0) | 2026.05.22 |
| [TIL] 건설 시스템 구조 확장 | 최종 팀프로젝트 (0) | 2026.05.21 |
| [TIL] 그리드 기반 건설 시스템 | 최종 팀프로젝트 (0) | 2026.05.19 |