LeeTaes 공부노트

[UE Project / FruitsPuzzle] 2. Tile & Texture Manager 본문

프로젝트/FruitsPuzzle

[UE Project / FruitsPuzzle] 2. Tile & Texture Manager

리태s 2024. 10. 15. 16:37
728x90
반응형

개요

이번 포스팅에서는 퍼즐의 기본이 되는 타일과, 타일에 입혀지는 텍스처를 관리하기 위한 텍스처 매니저에 대해 정리해보도록 하겠습니다.

Tile 구현 아이디어

타일은 개별적으로 생성되며, 생성과 동시에 타일의 타입과 인덱스를 지정받아 현재 자신의 타입에 따라 텍스처를 업데이트하도록 만들고 싶었습니다.

 

일반적으로 생각했을 때, 타일에 Texture의 배열을 만들고 현재 타일의 타입에 따라 배열에서 값을 선택해 적용시켜줄 수 있지만, 타일의 개수가 많아지게 되면 굳이 중복되는 불필요한 데이터(타일별 Texture배열)를 가지게 됩니다.

 

즉, Texture를 관리하는 Manager 클래스를 만들어 시작과 동시에 Texture Manager에 접근해 빠르게 원하는 Texture만을 뽑아오게 만들었습니다.

 

다음으로는 타일의 배치에 관한 이야기입니다.

타일은 위에서 생성되며 아래로 떨어지며 자신의 자리를 찾아가야 하며, 이를 위해 TargetLocation을 주고 Tick에서 꾸준히 TargetLocation으로 이동시켜주는 로직을 구현하게 되었습니다. 또한, 모든 타일의 움직임이 멈추면 전체 타일의 매칭 체크(폭파)를 해야하므로 DELEGATE를 생성해 앞으로 만들어줄 Tile을 관리하는 TileGrid클래스와 연결시켜줄 예정입니다.


Tile 구현 - TileType & TextureManager

먼저, 타일의 타입에 따라 모든 로직을 수행해야 하므로, 타일에 대한 정보를 구분짓기 위해 열거형을 선언해주었습니다.

TileType.h

다음으로 타일의 텍스쳐를 받아오기 위한 TextureManager를 만들어줘야 하는데, 언리얼 엔진에서는 매니저(싱글톤) 역할을 하는 GameInstance가 있으며 여기 추가해주기 위해 UObject를 상속받아 제작하게 되었습니다.

TextureManager

타입을 전달받아 바로 알맞는 Texture를 반환해주기위해 TMap 자료구조를 사용하였습니다.

생성자 함수에서는 필요한 텍스쳐들을 불러와 TextureMap에 저장해주었습니다.

(데이터 테이블이나 다른 방법도 많았지만 4개의 타일 이미지만 사용할 것이므로 하나씩 추가)

 

텍스쳐를 반환하는 것은 간단히 해당 타입과 일치하는 Key가 존재하는지 체크하는 방식으로 구현하였습니다.


Tile 구현 - Tile 생성 & Init & Move

타일은 생성과 동시에 초기화 되며, TargetLocation을 입력받는 순간 해당 위치까지 이동하게 됩니다.

 

타일을 구성하는 구성 요소는 클릭을 체크하기 위한 Collision,  실제 타일의 Mesh입니다.

생성자에서 컴포넌트를 초기화 해주고, Init() 함수에서 실제 Texture를 설정해주도록 합니다.

 

Tile.cpp

더보기
ATile::ATile()
{
    PrimaryActorTick.bCanEverTick = true;

    BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
    BoxComp->SetCollisionProfileName(TEXT("Tile"));
    SetRootComponent(BoxComp);


    TileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TileMesh"));
    TileMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    TileMesh->SetupAttachment(BoxComp);

    bIsMove = false;
    MoveSpeed = 200.0f;
}

void ATile::Init(ETileType Type, int32 Index)
{
    // 타일의 타입 설정
    TileType = Type;
    // 타일의 인덱스 설정
    TileIndex = Index;

    // 타입에 따른 이미지 설정
    UGameManager* GM = Cast<UGameManager>(GetGameInstance());
    if (GM && GM->GetTextureManager())
    {
        UMaterialInstanceDynamic* DynamicMaterial = UMaterialInstanceDynamic::Create(TileMesh->GetMaterial(0), this);
        if (DynamicMaterial)
        {
            DynamicMaterial->SetTextureParameterValue(FName(TEXT("Texture")), GM->GetTextureManager()->GetTileTexture(TileType));
        }

        TileMesh->SetMaterial(0, DynamicMaterial);
    }
}

참고로, DynamicMaterial에서 Texture를 설정해준 것은 제가 직접 만든 Material에서 사용하는 Texture를 파라미터로 설정해준 것입니다.

Tile에서 사용하는 Material

 

타일의 이동은 더욱 간단합니다.

 

TileGrid로부터 SetTargetLocaiton()함수를 호출받으면 그 순간부터 해당 TargetLocation으로 tick에서 이동하는 방식으로 만들었습니다.

 

또한, 모든 타일이 멈췄는지 체크해주기 위해 이동이 완료된 순간 TileGrid에 이벤트를 발생시켜주기 위해 델리게이트를 선언하였습니다.

 

Tile.Cpp

더보기
void ATile::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    if (bIsMove)
    {
        FVector MoveDir = (TargetLocation - GetActorLocation()).GetSafeNormal();
        FVector NewLocation = GetActorLocation() + MoveDir * MoveSpeed * DeltaTime;

        // 거리 체크
        if (FVector::Distance(NewLocation, TargetLocation) <= 10.0f)
        {
            SetActorLocation(TargetLocation);
            OnMoveEndDelegate.Execute(TileIndex);
            bIsMove = false;
        }
        else
        {
            SetActorLocation(NewLocation);
        }
    }
}

void ATile::SetTargetLocation(FVector Location)
{
    TargetLocation = Location;
    bIsMove = true;
}

결과

생성된 타일의 모습

728x90
반응형

'프로젝트 > FruitsPuzzle' 카테고리의 다른 글

[UE Project / FruitsPuzzle] 1. 프로젝트 개요  (0) 2024.10.15