언리얼 5

231023 언리얼을 활용한 2D Game 제작

슬뷔 2023. 10. 23. 10:37

스프라이트

프로젝트 세팅 -> 플러그인 -> 페이퍼 2D -> 스프라이트 아틀라스 그룹 활성화 체크 ( 따로 있는 텍스쳐를 atlas 처럼 뭉쳐준다 )

엔진 콘텐츠  표시, 플러그인 콘텐츠 표시 체크 해야 paper2d 검색가능!

 

2DGame 폴더 -> SpriteAtlas 폴더 -> 페이퍼2D -> 스프라이트 아틀라스 그룹 -> UIAtlas 생성

 

 

인스턴싱

-> GPU 인스턴싱을 사용하면 다중으로 복사된 동일한 메시의 오브젝트(인스턴스)를 한번에 렌더링하여 드로우콜 수치를 낮추고 렌더링 퍼포먼스를 향상시킬수있다. 씬에서 반복적으로 사용되는 건물, 나무, 기타 오브젝트에 사용할 수 있다.

 

2DGame 폴더 -> SpriteAtlas 폴더 -> 페이퍼2D -> 스프라이트 -> StartSprite 생성

2DGame 폴더 -> SpriteAtlas 폴더 -> 페이퍼2D -> 스프라이트 -> EndSprite 생성

UIAtlas 그룹에 추가한다.

UIAtlas

더블클릭하면 아래처럼 Atlas 이미지로 나온다.


APaperCharacter 을 상속 받은 ACharacter2D_Base 제작

ACharacter2D_Base 를 상속받은 BPC_Link 생성 

 

C++ Ureal3th_.Build.cs 에서 Paper 2D 추가

public class Unreal_3th : ModuleRules
{
	public Unreal_3th(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { 
			 "Paper2D"
		});

		PrivateDependencyModuleNames.AddRange(new string[] {  });
	}
}

 

ACharacter2D_Base.h 에서 #include "PaperFlipbook.h" 헤더 추가

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

#pragma once

#include "CoreMinimal.h"
#include "PaperCharacter.h"

#include "../Header/global.h"
#include "PaperFlipbook.h"
#include "Character2D_Base.generated.h"

UENUM(BlueprintType)
enum class EPLAYER_STATE : uint8
{
	IDLE,
	MOVE,
	ATTACK,
	JUMP,
	FALL,
	HIT,
	DEAD,
	NONE
};

UENUM(BlueprintType)
enum class EPLAYER_DIR : uint8
{
	LEFT,
	RIGHT
};

USTRUCT(Atomic, BlueprintType)
struct FFlipbookInfo
{
	GENERATED_BODY()
public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	EPLAYER_STATE	State;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	UPaperFlipbook* Flipbook;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	EPLAYER_DIR		Dir;

};

UCLASS()
class UNREAL_3TH_API ACharacter2D_Base : public APaperCharacter
{
	GENERATED_BODY()
	
private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Info", meta = (AllowPrivateAccess = "true"))
	TArray <FFlipbookInfo>	FlipbookInfoArr;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Info", meta = (AllowPrivateAccess = "true"))
	EPLAYER_DIR				CurDir;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Info", meta = (AllowPrivateAccess = "true"))
	EPLAYER_STATE			CurState;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component", meta = (AllowPrivateAccess = "true"))
	UCameraComponent*		Camera;

public:
	UCameraComponent* GetCamera() { return Camera; }

	bool ChangeState(EPLAYER2D_STATE _NextState, EPLAYER2D_DIR _Dir);
	void PlayFlipbook(EPLAYER_STATE _CurState, EPLAYER_DIR _CurDir, bool _bLoop = true, int32 _StartFrame = 0);

public:
	virtual void BeginPlay() override;
	virtual void Tick(float _DT) override;
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

#if WITH_EDITOR
	virtual void PostEditChangeProperty(FPropertyChangedEvent& _PropertyEvent) override;

#endif

public:
	ACharacter2D_Base();
	virtual ~ACharacter2D_Base();
};

BPC_Link(셀프) 에서 Flipbook Info Arr 값 추가

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


#include "Character2D_Base.h"

#include "PaperFlipbookComponent.h"

ACharacter2D_Base::ACharacter2D_Base()
	: CurState(EPLAYER_STATE::NONE)
{
	Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));

	Camera->SetupAttachment(GetRootComponent());
}

ACharacter2D_Base::~ACharacter2D_Base()
{
}

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

	CurDir = EPLAYER_DIR::RIGHT;
	ChangeState(EPLAYER_STATE::IDLE);
}

void ACharacter2D_Base::Tick(float _DT)
{
	Super::Tick(_DT);
}

void ACharacter2D_Base::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
}

bool ACharacter2D_Base::ChangeState(EPLAYER2D_STATE _NextState, EPLAYER2D_DIR _Dir)
{
	if (CurState == _NextState && CurDir == _Dir)
		return false;

	CurState = _NextState;
	CurDir = _Dir;

	switch (CurState)
	{
	case EPLAYER2D_STATE::IDLE:

		break;
	case EPLAYER2D_STATE::MOVE:

		break;
	case EPLAYER2D_STATE::ATTACK:

		break;
	case EPLAYER2D_STATE::JUMP:

		break;
	case EPLAYER2D_STATE::FALL:

		break;
	case EPLAYER2D_STATE::HIT:

		break;
	case EPLAYER2D_STATE::DEAD:

		break;	
	}

	PlayFlipbook(CurState, CurDir);

	return true;
}

void ACharacter2D_Base::PlayFlipbook(EPLAYER_STATE _CurState, EPLAYER_DIR _CurDir, bool _bLoop, int32 _StartFrame)
{
	for (int32 i = 0; i < FlipbookInfoArr.Num(); ++i)
	{
		if (_CurState == FlipbookInfoArr[i].State && _CurDir == FlipbookInfoArr[i].Dir)
		{
			if (IsValid(FlipbookInfoArr[i].Flipbook))
			{
				// paer flipbook 재생
				GetSprite()->SetFlipbook(FlipbookInfoArr[i].Flipbook);
				GetSprite()->SetPlaybackPositionInFrames(_StartFrame, false);
				GetSprite()->SetLooping(_bLoop);
				GetSprite()->Play();
			}

			return;
		}
	}
}

#if WITH_EDITOR
void ACharacter2D_Base::PostEditChangeProperty(FPropertyChangedEvent& _PropertyEvent)
{
	Super::PostEditChangeProperty(_PropertyEvent);

	PlayFlipbook(CurState, CurDir);
}
#endif