[C++] 간단한 문 만들기

Woogle·2022년 9월 10일
0

언리얼 엔진 5

목록 보기
13/60
post-thumbnail

블루프린트 없이 100% C++ 코드로만 문을 만들어보았다.

  • BoxCollision에 Overlap시 OnOverlapBegin과 OnOverlapEnd 함수를 바인딩했다.

  • Tick 함수에서 변수(DoorCurrentRotation, bIsOverlaped, bIsOverlaped)를 체크해서 OpenDoor, CloseDoor 함수로 분기되게 만들었다.

  • OpenDoor, CloseDoor 함수에서 DeltaTime을 받아 문의 각도를 조절했다.


📄 헤더 파일

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/BoxComponent.h"
#include "Door2.generated.h"

UCLASS()
class DOORCPP_API ADoor2 : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	ADoor2();

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
	UStaticMeshComponent* Door;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
	UStaticMeshComponent* Frame;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
	UBoxComponent* BoxCollision;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
	float MaxDoorAngle = 90.f;

	bool bIsOverlaped = false;

	float DoorCurrentRotation = 0.f;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UFUNCTION()
	void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	UFUNCTION()
	void OpenDoor(float DeltaTime);

	UFUNCTION()
	void CloseDoor(float DeltaTime);
};

📄 소스 파일

#include "Door2.h"

// Sets default values
ADoor2::ADoor2()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	BoxCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxCollision"));
	BoxCollision->InitBoxExtent(FVector(150.f, 100.f, 100.f));
	RootComponent = BoxCollision;

	Frame = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Frame"));
	Frame->SetRelativeLocation(FVector(0.f, 0.f, -100.f));
	Frame->SetupAttachment(RootComponent);

	Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Door"));
	Door->SetRelativeLocation(FVector(0.f, 45.f, -100.f));
	Door->SetupAttachment(RootComponent);

	static ConstructorHelpers::FObjectFinder<UStaticMesh>DoorSM(TEXT("'/Game/StarterContent/Props/SM_Door.SM_Door'"));
	if (DoorSM.Succeeded())
	{
		Door->SetStaticMesh(DoorSM.Object);
	}

	static ConstructorHelpers::FObjectFinder<UStaticMesh>FrameSM(TEXT("'/Game/StarterContent/Props/SM_DoorFrame.SM_DoorFrame'"));
	if (FrameSM.Succeeded())
	{
		Frame->SetStaticMesh(FrameSM.Object);
	}
}

// Called when the game starts or when spawned
void ADoor2::BeginPlay()
{
	Super::BeginPlay();

	BoxCollision->OnComponentBeginOverlap.AddDynamic(this, &ADoor2::OnOverlapBegin);
	BoxCollision->OnComponentEndOverlap.AddDynamic(this, &ADoor2::OnOverlapEnd);
}

// Called every frame
void ADoor2::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	UE_LOG(LogTemp, Warning, TEXT("bIsOverlaped : %s"), bIsOverlaped ? TEXT("true") : TEXT("false"));
	UE_LOG(LogTemp, Warning, TEXT("DoorCurrentRotation : %f"), DoorCurrentRotation);

	if (!bIsOverlaped && DoorCurrentRotation == 0.f)
	{
		return;
	}
	else if (bIsOverlaped)
	{
		OpenDoor(DeltaTime);
	}
	else
	{
		CloseDoor(DeltaTime);
	}
}

void ADoor2::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor != nullptr && OtherActor != this && OtherComp != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Overlap Begin"));
		bIsOverlaped = true;
	}
}

void ADoor2::OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (OtherActor != nullptr && OtherActor != this && OtherComp != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Overlap End"));
		bIsOverlaped = false;
	}
}

void ADoor2::OpenDoor(float DeltaTime)
{
	if (DoorCurrentRotation <= MaxDoorAngle)
	{
		FRotator NewRotation = FRotator(0.f, DeltaTime * 80, 0.f);
		Door->AddRelativeRotation(NewRotation);
		DoorCurrentRotation = Door->GetRelativeRotation().Yaw;
	}
}

void ADoor2::CloseDoor(float DeltaTime)
{
	if (DoorCurrentRotation >= 0.f)
	{
		FRotator NewRotation = FRotator(0.f, -DeltaTime * 80, 0.f);
		Door->AddRelativeRotation(NewRotation);
		DoorCurrentRotation = Door->GetRelativeRotation().Yaw;
	}
}

개선할 부분

  • Overlap되는 물체가 플레이어인지 체크하는 부분이 구현되어있지 않다.
  • Player의 키보드 E키 입력을 감지해서 열리는 부분이 구현되어있지 않다.

참고 자료

profile
노력하는 게임 개발자

0개의 댓글