기존에 만들었던 C++, BP 문을 개선해보았다.
https://velog.io/@woojoo0407/C-문-만들기
void Interact(); // 추가 함수
UPROPERTY(EditAnywhere)
float InteractLineTraceLength = 350.f; // 추가 변수
void ADoorCppCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
// ......
PlayerInputComponent->BindAction("Interact", IE_Pressed, this, &ADoorCppCharacter::Interact);
// ......
}
void ADoorCppCharacter::Interact()
{
if (FollowCamera == nullptr)
return;
FHitResult HitResult;
FVector Start = GetActorLocation();
FVector End = Start + GetActorForwardVector() * InteractLineTraceLength;
GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECollisionChannel::ECC_Visibility);
ADoor_Cpp* Door = Cast<ADoor_Cpp>(HitResult.GetActor());
if (Door)
{
Door->OnInteract(); // 문의 메소드를 호출
}
}
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "GameFramework/Character.h"
#include "Components/TimelineComponent.h"
#include "Components/BoxComponent.h"
#include "Door_Cpp.generated.h"
UCLASS()
class DOORCPP_API ADoor_Cpp : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ADoor_Cpp();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
UBoxComponent* BoxCollision;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
UStaticMeshComponent* Door;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
UStaticMeshComponent* Frame;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Door")
float DoorRotateAngle = 90.f; // 문의 최대 회전 각도
UPROPERTY(EditAnywhere)
FTimeline Timeline; // Timeline 생성
UPROPERTY(EditAnywhere)
UCurveFloat* CurveFloat; // Timeline 커브
bool bIsDoorClosed = true;
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 OnInteract(); // 캐릭터의 LineTrace를 받는 메소드
UFUNCTION()
void OpenDoor(float Value); // Bind function
};
#include "Door_Cpp.h" // 추가 헤더
// Sets default values
ADoor_Cpp::ADoor_Cpp()
{
// 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"));
Frame = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Frame"));
Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Door"));
RootComponent = BoxCollision;
Frame->SetupAttachment(RootComponent);
Door->SetupAttachment(RootComponent);
}
// Called when the game starts or when spawned
void ADoor_Cpp::BeginPlay()
{
Super::BeginPlay();
if (CurveFloat) // Timeline에 OpenDoor 함수를 바인딩
{
FOnTimelineFloat TimelineProgress;
TimelineProgress.BindDynamic(this, &ADoor_Cpp::OpenDoor);
Timeline.AddInterpFloat(CurveFloat, TimelineProgress);
}
}
// Called every frame
void ADoor_Cpp::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
Timeline.TickTimeline(DeltaTime); // Timeline에 DeltaTime을 적용
}
void ADoor_Cpp::OpenDoor(float Value)
{
FRotator Rot = FRotator(0.f, DoorRotateAngle * Value, 0.f);
Door->SetRelativeRotation(Rot);
}
void ADoor_Cpp::OnInteract()
{
UE_LOG(LogTemp, Warning, TEXT("Interact!"));
if (bIsDoorClosed)
{
UE_LOG(LogTemp, Warning, TEXT("Open!"));
Timeline.Play(); // Open the door
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Close!"));
Timeline.Reverse(); // Close the door
}
bIsDoorClosed = !bIsDoorClosed; // Flip flop
}