Replicated

[Drag Down] 메시 변경 UI, USceneCaptureComponent2D 본문

언리얼 엔진/Drag Down

[Drag Down] 메시 변경 UI, USceneCaptureComponent2D

라구넹 2025. 5. 7. 21:09

일단 완성 시 이렇게 된다

가까이에서 캐릭터를 보여주고, 옆에 캐릭터 외형 버튼이 있다

 

선택 시 적용된다

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "DataAsset/DDMeshDatas.h"
#include "DDCharacterChangeButtonWidget.generated.h"

/**
 * 
 */
UCLASS()
class DRAGDOWN_API UDDCharacterChangeButtonWidget : public UUserWidget
{
	GENERATED_BODY()
	
public:
	virtual void NativeConstruct() override;

	UFUNCTION(BlueprintCallable)
	FORCEINLINE void SetMeshID(EMESHID InMeshID) { MeshID = InMeshID; }

	UFUNCTION(BlueprintCallable)
	void SetMeshDescription(FText InDescription);

protected:
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UButton> BtnChangeCharacterAppearance;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UTextBlock> TxtChangeCharacterAppearance;

	EMESHID MeshID;

	UFUNCTION()
	void OnClickedCallback();

	bool CanChangeAppearance();
};


// Fill out your copyright notice in the Description page of Project Settings.


#include "UI/DDCharacterChangeButtonWidget.h"
#include "GameFramework/Character.h"
#include "Components/Button.h"
#include "Components/TextBlock.h"
#include "Kismet/GameplayStatics.h"
#include "DataAsset/DDMeshDatas.h"
#include "ActorComponent/DDMeshManagerComponent.h"
#include "DragDown.h"

void UDDCharacterChangeButtonWidget::NativeConstruct()
{
	if (BtnChangeCharacterAppearance)
	{
		BtnChangeCharacterAppearance->OnClicked.AddDynamic(this, &UDDCharacterChangeButtonWidget::OnClickedCallback);

		if (!CanChangeAppearance())
		{
			BtnChangeCharacterAppearance->SetIsEnabled(false);
		}
	}
}

void UDDCharacterChangeButtonWidget::SetMeshDescription(FText InDescription)
{
	if ( TxtChangeCharacterAppearance )
	{
		TxtChangeCharacterAppearance->SetText(InDescription);
	}
}

void UDDCharacterChangeButtonWidget::OnClickedCallback()
{
	if (!CanChangeAppearance()) return;

	ACharacter* Character = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
	if ( Character == nullptr )
	{
		UE_LOG(LogDD, Error, TEXT("No Player Character"));
		return;
	}

	if ( UDDMeshManagerComponent* MeshManager = Character->GetComponentByClass<UDDMeshManagerComponent>() )
	{
		MeshManager->SetMergedMesh(MeshID);
	}
}

bool UDDCharacterChangeButtonWidget::CanChangeAppearance()
{
	// 추후 서버와 연동하여 체크
	return true;
}

각각 버튼 UI

CanChangeAppearance에서 승 수같은 거 체크해서 사용 가능한 UI인지 체크할 것임

 

상위 UI 형태

스크롤 박스 안에 버티컬 박스

 

상위 위젯에서 타입이랑 텍스트 초기화

 

 

USceneCaptureComponent2D

일단 렌더 타겟이랑 메테리얼 필요

메테리얼에서 렌더 타겟 뜯어오면 됨

 

렌더 타겟은 어디서 설정하나? => USceneCaptureComponent2D

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "DDUICamera.generated.h"

UCLASS()
class DRAGDOWN_API ADDUICamera : public AActor
{
	GENERATED_BODY()
	
public:	
	ADDUICamera();

public:	
	virtual void BeginPlay() override;
	virtual void Tick(float DeltaTime) override;

protected:
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TObjectPtr<class USceneCaptureComponent2D> Capture;

	UPROPERTY()
	TObjectPtr<ACharacter> Character;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Offset")
	FVector Offset;
};

// Fill out your copyright notice in the Description page of Project Settings.


#include "Actor/DDUICamera.h"
#include "Components/SceneCaptureComponent2D.h"
#include "GameFramework/Character.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetMathLibrary.h"

ADDUICamera::ADDUICamera()
{
	PrimaryActorTick.bCanEverTick = true;

	Capture = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("Capture"));
	SetRootComponent(Capture);
	Offset = FVector(-100.0f, 0.0f, 7.0f);
}

void ADDUICamera::BeginPlay()
{
	Super::BeginPlay();

	Character = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
}

void ADDUICamera::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FVector StartLocation = Character->GetActorLocation() + Offset;
	FVector TargetLocation = Character->GetActorLocation();
	SetActorLocation(StartLocation);

	FRotator LookAtRotation = UKismetMathLibrary::FindLookAtRotation(StartLocation, TargetLocation);
	SetActorRotation(LookAtRotation);
}

* Offset은 블루프린트에서 적당히 조정

* 처음에 블루프린트로 만들었는데, Tick 쓰다보니 성능 좀 신경쓰여서 그냥 C++로 만듦

이 액터가 카메라처럼 3D 공간을 찍어서 2D로 만들고 렌더 타겟에 설정해준다

이 경우 움직이는 캐릭터를 찍기 때문에 Tick에서 카메라 액터의 Location, Rotation을 설정해줘야 한다

그리고 각 레벨에 배치 필요

 

상속해서 블루프린트로 만들고

 

텍스쳐 타겟에 렌더 타겟 설정

뭐 숨기고 싶은 거 있으면 이거 설정하고

Show Only Actor Components에 플레이어 넣으면 된다

 

이제 런타임에 캐릭터 메시 병합 및 변경하고 카메라로 보여주는 UI까지 제작 완료