[25.06.29] :: 가디언 앤 시커 프로젝트 20

chooha·2025년 6월 29일

가디언앤시커

목록 보기
20/25

📍 컨텐츠 설명

"퍼즐을 풀듯 전략을 짜고, RPG처럼 성장하는 룬 시스템"

가디언 앤 시커는 퍼즐과 RPG의 융합을 통해 전략적 성장의 재미를 제공합니다. 씨커 플레이어는 클래스 별 아케인 보드에 다양한 모양의 룬을 배치하여 스탯을 커스터마이징하고, 자신만의 빌드를 구축할 수 있습니다. 제한된 공간에서 최적의 조합을 찾는 전략적 선택이 승패를 좌우합니다.

  • 그리드 보드에 테트리스 모양의 룬 블록 배치
  • 각 룬은 고유한 스탯 효과를 제공 (ATK, DEF, HP, AGL, ATS)
  • 드래그 앤 드롭 방식의 직관적인 룬 배치 시스템
  • 특수 셀과 연결된 룬은 추가 보너스 스탯 획득
  • 실시간 스탯 계산 및 UI 업데이트
  • 클래스별 전용 그리드 레이아웃으로 차별화된 전략 제공
  • 로컬 저장/로드 시스템으로 빌드 유지

이 시스템을 통해 씨커 플레이어들은 단순한 스탯 강화를 넘어서, 자신만의 독특한 전략과 플레이 스타일을 구현할 수 있는 깊이 있는 성장 시스템을 경험할 수 있습니다.

컨텐츠 진화 과정
프로토타입: 마우스 위치 기준 단순 좌표 계산
→ 마우스 아래 그리드 셀을 (0,0)으로 하여 룬 Shape 오프셋 계산

중간 발표: 스마트 배치 시스템 도입
→ 마우스 위치에서 가능한 모든 배치 후보 중 최적 위치 자동 선택

최종 구현: 직관적 드래그 비주얼 시스템
→ 드래그 위젯을 룬 모양대로 생성된 그리드로 구현하여 배치 예측성 향상
→ 룬별 마우스 커서 제어와 복잡한 배치 검증 로직 문제 완전 해결


룬 시스템 시스템 구조와 구현 상세

시스템 전체 구조

룬 시스템은 아케인 보드 매니저(UGS_ArcaneBoardManager), UI 위젯들, 로컬 플레이어 서브시스템(UGS_ArcaneBoardLPS)로 구성됩니다.

핵심 컴포넌트

  • ArcaneBoardManager: 룬 배치, 스탯 계산, 연결 시스템 관리
  • ArcaneBoardWidget: 메인 UI, 마우스 이벤트 처리, 드래그 앤 드롭
  • DragVisualWidget: 드래그 중 룬 미리보기 표시
  • RuneGridCellWidget: 개별 그리드 셀 관리
  • ArcaneBoardLPS: 저장/로드, 캐릭터별 데이터 관리

룬 배치 시퀀스 다이어그램


📍 컨텐츠 진화 과정 및 구현 설명

프로토타입 : 마우스 위치 기준 단순 좌표 계산

→ 마우스 아래 그리드 셀을 (0,0)으로 하여 룬 Shape 오프셋 계산

기술적 구현 방식

룬의 모양은 TMap<FIntPoint, UTexture2D*> 구조로 저장되어 있습니다. 예를 들어 L자 형태의 룬은 3개의 Fragment로 구성됩니다: (0,0), (1,0), (1,1) 좌표에 각각 다른 텍스처 조각이 할당되어 있습니다.

// 룬 배치 검증 로직
FIntPoint CellPos = TargetCell->GetCellPos(); // 마우스 클릭 위치
for (const FIntPoint& Offset : RuneShape)
{
    FIntPoint FinalPos = CellPos + Offset; // 기준점 + 오프셋
    if (!IsValidCell(FinalPos)) return false; // 유효성 검사
}

플레이어가 마우스로 룬을 그리드 위에 드래그하면, 마우스 커서 아래 그리드 셀을 기준점(0,0)으로 잡고 Offset을 계산합니다:

  • 기준 셀 (0,1)에서 계산: (0,1), (1,1), (1,2) → 모든 좌표가 유효한 빈 셀이므로 배치 가능
  • 기준 셀 (0,3)에서 계산: (0,3), (1,3), (1,4) → 그리드 범위를 벗어나므로 배치 불가능

배치가 가능한 그리드 셀을 클릭하면 각 그리드 셀의 텍스처 이미지를 해당 룬의 텍스처로 렌더링합니다.

❌ 문제 : 정확한 셀을 클릭하지 않으면 배치되지 않음


중간 발표 이후 개선 : 스마트 배치 시스템 도입

→ 마우스 위치에서 가능한 모든 배치 후보 중 최적 위치 자동 선택

기술적 구현 방식

클릭한 셀을 포함할 수 있는 모든 가능한 배치 위치를 계산하고, 그 중 가장 직관적인 위치를 자동 선택하는 시스템을 구현했습니다.

bool FindOptimalPlacementPosition(uint8 RuneID, const FIntPoint& ClickedCell, FIntPoint& OutBestPosition)
{
    TArray<FIntPoint> ValidPositions;
    
    // 룬의 각 셀에 대해 클릭한 셀이 해당 위치에 올 수 있는지 확인
    for (const FIntPoint& ShapeOffset : RuneShape)
    {
        FIntPoint CandidatePosition = ClickedCell - ShapeOffset;
        if (CanPlaceRuneAt(RuneID, CandidatePosition))
        {
            ValidPositions.Add(CandidatePosition);
        }
    }
    
    // 우선순위 선택: 룬의 좌상단([0,0])에 가까운 순서
    for (const FIntPoint& Position : ValidPositions)
    {
        FIntPoint ShapeOffset = ClickedCell - Position;
        // Y좌표가 작을수록, 같다면 X좌표가 작을수록 우선
        if (ShapeOffset.Y < BestShapeOffset.Y || 
           (ShapeOffset.Y == BestShapeOffset.Y && ShapeOffset.X < BestShapeOffset.X))
        {
            OutBestPosition = Position;
        }
    }
}

❌ 문제 : 여전히 드래그 위젯에 커서가 룬 별로 다르게 위치하기 때문에 실제 그리드 위치에 직관적으로 일치하지 않음


최종 구현 : 직관적 드래그 비주얼 시스템

→ 드래그 위젯을 룬 모양대로 생성된 그리드로 구현하여 클릭한 보드 그리드 셀과 룬 드래그 위젯의 커서가 위치한 셀을 일치시켜서 보이는 그대로 배치

< 기술적 구현 방식 >

기존의 단일 이미지 + 복잡한 오프셋 계산 방식을 버리고, 드래그 비주얼 자체를 룬 모양에 맞는 그리드로 생성하는 방식으로 전환했습니다.

- DragVisualWidget 구조 변경

// 기존: 단일 이미지
UImage* RuneImage;

// 새로운: 룬 모양 그리드
UUniformGridPanel* RuneGridPanel;
TMap<FIntPoint, UImage*> GridCellWidgets; // 각 셀별 위젯

- 기준셀 기반 위치 계산

룬의 기준셀(0,0)이 항상 마우스 커서에 위치되도록 구현했습니다.

void UGS_DragVisualWidget::CalculateInitReferenceCellOffset()
{
    if (CachedRuneShape.Contains(ReferenceCellPos) && CellToGridPosMap.Contains(ReferenceCellPos))
    {
        FIntPoint ActualGridPos = CellToGridPosMap[ReferenceCellPos];
        FVector2D ActualCellSize = BaseCellSize * CurrentScaleFactor;
        
        // 기준셀의 중심점을 마우스 커서에 맞춤
        FVector2D BaseOffset = FVector2D(
            ActualGridPos.Y * ActualCellSize.X + ActualCellSize.X * 0.5f,
            ActualGridPos.X * ActualCellSize.Y + ActualCellSize.Y * 0.5f
        );
        
        ReferenceCellOffset = BaseOffset;
    }
}

룬 테이블에서 마우스 커서가 위치하길 원하는 룬의 그리드 위치 좌표를 0,0으로 설정해주면 어떤 모양의 룬이 생성되더라도 0,0으로 지정해준 룬의 그리드 위치에 마우스 커서가 위치합니다.

- 배치 로직 단순화

복잡한 예측 계산을 제거하고 직관적인 배치 로직으로 변경했습니다.

// 기존: 복잡한 예측 계산
FIntPoint OptimalPos;
if (BoardManager->FindOptimalPlacementPosition(SelectedRuneID, ClickedCellPos, OptimalPos))

// 새로운: 단순한 직접 배치  
FIntPoint PlacementPos = TargetCell->GetCellPos(); // 마우스 위치 = 배치 위치
if (BoardManager->CanPlaceRuneAt(SelectedRuneID, PlacementPos))

✅ 시각적으로 보이는 그대로 기능하여 배치 예측성 향상
✅ 룬별 드래그 위젯의 마우스 커서 위치 문제와 복잡한 배치 검증 로직 문제 완전 해결

0개의 댓글