이제는 Trigger Box에 닿았을 때가 아니라 버튼을 눌렀을 때 문을 열고 닫을 수 있도록 할 것이다.
문을 열고 닫게 하는 Door Button Class를 만들어주었고, 문을 열고 닫도록 Delgate를 사용해서 Door에 문 열고 닫으라는 명령을 전달할 수 있도록 했다.
스테이지가 클리어 되었다는 정보를 Delegate로 받아온 상태, 이 상태에서 플레이어와 버튼이 닿았을 때 문을 열고 닫을 수 있도록 해주었다.
Overlap 함수를 호출하는건 BeginPlay에서 하는게 맞지만, 코드를 작성하다보니 Overlap을 호출해주는 함수를 따로 빼주었다. 물론 문제없이 호출도 잘 되고, 문도 잘 움직인다. 정돈이 필요한 상태..
Delegate 함수를 호출하는 것이 아직은 어색하지만 이렇게 또 한발자국 다가갈 수 있었다.
Door.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "DoorButton.generated.h"
DECLARE_DELEGATE(FOpenDoorDele)
UCLASS()
class SPACEESCAPE_API ADoorButton : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ADoorButton();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditDefaultsOnly, Category = "Door Button Settings")
class UBoxComponent* boxComp;
UPROPERTY(EditDefaultsOnly, Category = "Door Button Settings")
class UStaticMeshComponent* buttonMesh;
//손이 버튼에 닿으면 문이 열린다
UFUNCTION()
void OnHandOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
UFUNCTION()
void CheckClearStage();
//문을 열어라 지시할것
UFUNCTION()
void ReportOpen();
void NoReportOpen();
public:
class ADoors* door;
class AEscapePlayer* player;
FOpenDoorDele openDoorDele;
};
Door.cpp
#include "DoorButton.h"
#include "EscapePlayer.h"
#include "Components/BoxComponent.h"
#include "RoomManager.h"
#include "EngineUtils.h"
// Sets default values
ADoorButton::ADoorButton()
{
// 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;
boxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("boxComp"));
SetRootComponent(boxComp);
buttonMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("buttonMesh"));
buttonMesh->SetupAttachment(RootComponent);
}
// Called when the game starts or when spawned
void ADoorButton::BeginPlay()
{
Super::BeginPlay();
for (TActorIterator<ARoomManager> it(GetWorld()); it; ++it)
{
ARoomManager* rm = *it;
rm->stageClearDele.AddUFunction(this, FName("CheckClearStage"));
}
}
// Called every frame
void ADoorButton::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ADoorButton::OnHandOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
player = Cast<AEscapePlayer>(OtherActor);
player != nullptr ? ReportOpen() : NoReportOpen();
}
void ADoorButton::CheckClearStage()
{
boxComp->OnComponentBeginOverlap.AddDynamic(this, &ADoorButton::OnHandOverlap);
UE_LOG(LogTemp, Warning, TEXT("CheckClearStage"))
}
void ADoorButton::ReportOpen()
{
UE_LOG(LogTemp, Warning, TEXT("CheckClearStage : Puzzle Clear, Character and DoorButton"))
openDoorDele.Execute();
}
void ADoorButton::NoReportOpen()
{
UE_LOG(LogTemp, Warning, TEXT("NoReportOpen"))
return;
}
DoorButton.h
#pragma once
#include "CoreMinimal.h"
#include "Components/TimelineComponent.h"
#include "GameFramework/Actor.h"
#include "Doors.generated.h"
class UCurveFloat;
UCLASS()
class SPACEESCAPE_API ADoors : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ADoors();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
/*퍼즐풀기를 완료하면 양 옆으로 열리는 문*/
UPROPERTY(EditDefaultsOnly, Category = "Door Settings")
class UStaticMeshComponent* doorMesh;
UFUNCTION()
void Open();
UFUNCTION()
void Close();
//문 여는 충돌감지 진행중인가
bool bIsOpenOverlaping = true;
UFUNCTION()
void ChangeDoorOverlaping();
/*문의 부드러운 이동*/
UFUNCTION()
void TimeLineProgress(float val);
FTimeline curveTimeline;
UPROPERTY()
FVector startPoint;
UPROPERTY()
FVector endPoint;
UPROPERTY(EditDefaultsOnly, Category = "DoorTimeLine")
float yOffset = 200;
UPROPERTY(EditDefaultsOnly, Category = "DoorTimeLine")
UCurveFloat* curveFloat;
//문 최초 위치
FVector initLoc;
};
DoorButton.cpp
#include "Doors.h"
#include "Components/TimelineComponent.h"
#include "DoorButton.h"
#include "EngineUtils.h"
// Sets default values
ADoors::ADoors()
{
// 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;
this->RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
doorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("doorMesh"));
doorMesh->SetupAttachment(RootComponent);
doorMesh->SetRelativeLocation(FVector(0, 0, 0));
doorMesh->SetRelativeScale3D(FVector(1, 4.625f, 2.4f));
initLoc = GetActorLocation();
}
// Called when the game starts or when spawned
void ADoors::BeginPlay()
{
Super::BeginPlay();
for(TActorIterator<ADoorButton> it(GetWorld()); it; ++it)
{
ADoorButton* db = *it;
db->openDoorDele.BindUFunction(this, FName("ChangeDoorOverlaping"));
initLoc = GetActorLocation();
if (curveFloat)
{
FOnTimelineFloat TimeLineProgress;
TimeLineProgress.BindUFunction(this, FName("TimeLineProgress"));
curveTimeline.AddInterpFloat(curveFloat, TimeLineProgress);
}
}
}
// Called every frame
void ADoors::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
curveTimeline.TickTimeline(DeltaTime);
}
void ADoors::ChangeDoorOverlaping()
{
bIsOpenOverlaping == true ? Open() : Close();
}
void ADoors::Open()
{
startPoint = GetActorLocation();
endPoint = startPoint + FVector(0, yOffset, 0);
curveTimeline.PlayFromStart();
UE_LOG(LogTemp, Warning, TEXT("Overlapped : Open Door"))
bIsOpenOverlaping = false;
}
void ADoors::Close()
{
if (bIsOpenOverlaping == true) return;
startPoint = GetActorLocation();
endPoint = initLoc;
curveTimeline.PlayFromStart();
bIsOpenOverlaping = true;
UE_LOG(LogTemp, Warning, TEXT("EndOverlapped : Close Door"))
}
void ADoors::TimeLineProgress(float val)
{
FVector newLoc = FMath::Lerp(startPoint, endPoint, val);
SetActorLocation(newLoc);
}
아직 구현이 완성된 것은 아니다.
문이 열고 닫히기 위한 조건들이 아직 남아있기 때문이다. 허허...
Delegate 어렵다
Delegate에 대해 알 수 있는 좋은 블로그를 하나 남겨두며 20000
https://darkcatgame.tistory.com/66
UE4 C++ Delegate 정리 & 샘플 프로젝트
개인적으로 UE4 C++에서 Delegate를 사용할 때 처음에 굉장히 에러를 많이 겪었습니다, 그래서 이번 포스팅은 UE4 C++에서 Delegate를 사용하는 방법에 대해 정리하고 샘플프로젝트도 만들었습니다. https
darkcatgame.tistory.com
'언리얼엔진 개발 > VR' 카테고리의 다른 글
[UnrealEngine5] VR 나사 돌리기 만들기(2) (1) | 2023.05.12 |
---|---|
[UnrealEngine5] VR 나사 돌리기 만들기(1) (2) | 2023.05.11 |
[UnrealEngine5]버튼을 누르면 문 열고 닫기 C++ (4) (0) | 2023.04.28 |
[UnrealEngine5]버튼을 누르면 문 열고 닫기 C++ (3) (0) | 2023.04.25 |
[UnrealEngine5]버튼을 누르면 문 열고 닫기 C++ (1) (0) | 2023.04.23 |