이 튜토리얼에서는 타임라인 블루프린트를 사용해 언리얼 시작용 콘텐츠(Engine Starter content) 에 포함된 리소스로 근접성 기반 문 열기 기능을 만드는 방법을 설명합니다.
(convert:false)
문 액터 만들기
-
먼저 새 프로젝트...(New) > 게임(Games) > 기본(Blank) > 블루프린트(Blueprint) 프로젝트를 만듭니다. 이 때 시작용 콘텐츠(Starter Content) 를 활성화하고, 프로젝트 이름은 TimelineDoorActor 로 합니다.
-
추가/임포트(Add/Import) 버튼을 눌러 BP_DoorActor 라는 이름의 새 블루프린트 액터(Actor) 클래스를 생성합니다.
-
콘텐츠 브라우저에서 BP_DoorActor를 클릭해서 블루프린트 에디터를 연 다음 클래스 디폴트(Class Defaults) 를 엽니다.
(w:624 h:413 convert:false) -
컴포넌트(Components) 탭에서 컴포넌트 추가(Add Component) 버튼을 클릭하고 스태틱 메시(Static Mesh) 를 선택해 새 스태틱 메시 컴포넌트(Static Mesh Component) 를 추가합니다.
(w:368 h:681 convert:false) -
스태틱 메시 컴포넌트를 우클릭한 다음 이름변경(Rename) 을 선택해 컴포넌트 이름을 DoorFrame 으로 변경합니다.
(w:410 h:313 convert:false) -
컴포넌트(Components) 탭에서 컴포넌트 추가(Add Component) 버튼을 클릭하고 스태틱 메시(Static Mesh) 를 선택해 새 스태틱 메시 컴포넌트(Static Mesh Component) 를 추가합니다. (세 번째 단계 반복)
-
스태틱 메시 컴포넌트를 우클릭한 다음 이름변경(Rename)을 선택해 컴포넌트 이름을 Door 로 변경합니다.
(w:412 h:282 convert:false) -
컴포넌트 추가(Add Component)를 클릭한 뒤 드롭다운 메뉴에서 박스 콜리전(Box Collision) 을 선택하고 이름을 Box로 변경합니다.
(w:254 h:465 convert:false) -
이제 이벤트 그래프를 열고 그래프를 우클릭한 다음 블루프린트 컨텍스트 메뉴(Blueprint Context Menu) 에서 타임라인 추가(Add Timeline) 를 선택합니다. 타임라인 이름을 DoorTimelineComponent 로 지정합니다.
(w:489 h:322 convert:false)
이제 BP_DoorActor의 클래스 디폴트는 아래 예시와 같은 모습이어야 합니다.
(w:624 h:392 convert:false)
문 스태틱 메시 구성하기
다음은 컴포넌트(Components) 탭의 어태치먼트 계층구조를 구성할 차례입니다.
그리고 DoorFrame 과 Door 스태틱 메시 컴포넌트를 시각적으로 나타낼 스태틱 메시 에셋도 구성해야 합니다.
-
BP_DoorActor 의 컴포넌트 탭에서 DoorFrame 스태틱 메시를 선택한 다음 DefaultSceneRoot 컴포넌트 로 드래그하여 새 루트 컴포넌트(root component) 를 만듭니다.
(w:412 h:402 convert:false) -
이제 컴포넌트 탭에서 DoorFrame 스태틱 메시를 선택한 다음 디테일(Details) 패널 에서 스태틱 메시를 SM_DoorFrame 으로 변경합니다.
(w:624 h:361 convert:false) -
컴포넌트 패널에서 DoorMesh 컴포넌트를 선택합니다. 디테일 패널로 이동한 뒤 스태틱 메시를 SM_Door 로 변경합니다.
(w:624 h:409 convert:false) -
그리고 트랜스폼(Transform) 카테고리에서 Y 위치(Y Location) 값을 45.0 으로 설정합니다.
(w:624 h:462 convert:false) -
저장(Save) 과 컴파일(Compile) 을 클릭해 변경사항을 Bp_DoorActor에 저장합니다.
타임라인 플로트 트랙 만들기
타임라인 컴포넌트에는 동작 애니메이션을 만드는 키와 커브가 필요합니다. 각 커브에서는 시간과 값을 정의하는 키가 하나 이상 있습니다. 커브는 키 사이를 보간해 타임라인의 특정 시점에 대한 값을 계산합니다.
-
먼저 이벤트 그래프에서 DoorTimelineComponent를 더블클릭해 타임라인 에디터를 엽니다.
-
플로트 커브 추가(Add Float Curve) 를 클릭해 트랙에 새 커브를 추가하고 커브 이름을 DoorRotationZ 로 설정합니다.
(w:481 h:214 convert:false) -
우클릭하여 플로트 커브 트랙에 두 개의 키를 추가합니다. 첫 번째 키의 값은 (0,0), 두 번째 키의 값은 (5,90)으로 합니다.
(w:624 h:309 convert:false) -
시프트(Shift) 키를 누른 채로 두 키를 모두 선택한 다음 우클릭하여 키 보간(Key Interpolation) 드롭다운 메뉴에서 자동(Auto) 보간을 선택합니다.
-
플로트 트랙을 저장합니다.
이벤트 트랙 로직 업데이트
이제 Door 스태틱 메시가 회전할 수 있도록 업데이트 로직을 만들어야 합니다.
-
BP_DoorActor의 컴포넌트 탭에서 Door 스태틱 메시를 이벤트 그래프로 드래그합니다.
(w:624 h:498 convert:false) -
Door 핀을 드래그하면 나타나는 컨텍스트 메뉴의 액션 중에서 SetRelativeRotation 을 선택합니다.
(w:510 h:448 convert:false) -
이벤트 그래프에서 우클릭한 뒤 컨텍스트 메뉴에서 Make Rotator 를 선택합니다.
(w:624 h:534 convert:false) -
DoorTimelineComponent 노드에서 Door Rotation Z 플로트 핀을 드래그하여 Make Rotator 노드의 Z (Yaw ) 핀에 연결합니다.
(w:624 h:408 convert:false) -
DoorTimelineComponent 노드에서 Update 핀 을 드래그하여 SetRelativeRotation 노드의 입력 실행 핀에 연결합니다.
-
Make Rotator 노드에서 Return Value 핀을 SetRelativeRotation 노드의 New Rotation 핀에 연결합니다.
(w:624 h:409 convert:false) -
컴파일(Compile) 하고 저장(Save) 합니다.
박스 콜리전 오버랩 이벤트 생성 및 바인딩
박스 컴포넌트는 액터가 콜리전 바운드를 드나들 때 반응해야 합니다.
-
BP_DoorActor의 컴포넌트 탭에서 Box 컴포넌트를 선택합니다.
-
디테일(Details) 패널에서 이벤트(Events) 카테고리로 스크롤을 내려 컴포넌트 오버랩 시작 시(On Component Begin Overlap) 이벤트 옆에 있는 + 아이콘을 클릭합니다.
(w:624 h:406 convert:false) -
컴포넌트 오버랩 시작 시(Box)(On Component Begin Overlap(Box)) 노드에서 실행 핀을 드래그하여 DoorTimelineComponent 노드의 Play 핀에 연결합니다.
(w:624 h:312 convert:false) -
BP_DoorActor의 컴포넌트 탭에서 Box 컴포넌트를 선택합니다. 디테일(Details) 패널에서 이벤트(Events) 카테고리로 스크롤을 내려 컴포넌트 오버랩 종료 시(On Component End Overlap) 이벤트 옆에 있는 + 아이콘을 클릭합니다.
(w:624 h:446 convert:false) -
컴포넌트 오버랩 종료 시(Box)(On Component End Overlap(Box)) 노드에서 실행 핀을 드래그하여 DoorTimelineComponent 노드의 Reverse 핀에 연결합니다.
(w:624 h:346 convert:false) -
컴파일(Compile) 하고 저장(Save) 합니다.
레벨에 액터 배치하기
-
콘텐츠 브라우저에서 BP_DoorActor를 선택하고 뷰포트로 드래그합니다.
(w:624 h:518 convert:false) -
PIE를 누릅니다.
WASD 키를 이용해 관중 폰을 컨트롤할 수 있습니다. DoorActor의 콜리전 바운드로 들어가면 타임라인이 재생되면서 문이 열리는 것을 볼 수 있습니다. 바운드를 나가면 타임라인이 거꾸로 재생됩니다.
완성된 블루프린트
BP_DoorActor
(w:624 h:384 convert:false)
C++ 타임라인 예시와 엔진 시작용 콘텐츠(Engine Starter content) 의 리소스를 사용해 일반적인 근접성 기반 문 열기 기능을 구성합니다.
(convert:false)
문 액터 만들기
- 먼저 새 프로젝트...(New) > 게임(Games) > 기본(Blank) > C++ 프로젝트를 만듭니다. 이 때 시작용 콘텐츠(Starter Content) 를 활성화하고, 프로젝트 이름은 TimelineDoorActor 로 합니다.
-
C++ 클래스 마법사(Class Wizard) 에서 DoorActor 라는 이름의 신규 액터(Actor) 클래스를 만듭니다.
DoorActor.h파일로 이동한 뒤 다음을 선언합니다.#include "Components/TimelineComponent.h" -
DoorActor클래스 정의에서 다음 코드를 구현합니다.protected: //Door 에셋을 나타내는 MeshComponents UPROPERTY(VisibleAnywhere, BlueprintReadWrite) UStaticMeshComponent* DoorFrame; UPROPERTY(VisibleAnywhere, BlueprintReadWrite) UStaticMeshComponent* Door; //Door 메시를 애니메이트하는 TimelineComponent UPROPERTY(VisibleAnywhere, BlueprintReadWrite) UTimelineComponent* DoorTimelineComp; //근접성 볼륨으로 사용할 BoxComponent UPROPERTY(EditAnywhere, BlueprintReadWrite) class UBoxComponent* DoorProxVolume; -
DoorActor.cpp으로 이동합니다. 박스 컴포넌트를 사용하려면 아래 클래스 라이브러리를 포함해야 합니다.#include "Components/BoxComponent.h" -
ADoorActor::ADoorActor 의 생성자에서 다음을 선언합니다.
//디폴트 컴포넌트 생성 DoorFrame = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorFrameMesh")); Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh")); DoorTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("DoorTimelineComp")); DoorProxVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("DoorProximityVolume")); //어태치먼트 구성 DoorFrame->SetupAttachment(RootComponent); Door->AttachToComponent(DoorFrame,FAttachmentTransformRules::KeepRelativeTransform); DoorProxVolume->AttachToComponent(DoorFrame, FAttachmentTransformRules::KeepRelativeTransform);
참고: 이후에 Door 액터의 커스텀 메서드로 조정할 수 있도록 문의 상대적 트랜스폼은 어태치먼트 규칙으로 유지합니다. 자세한 문서는 어태치먼트 트랜스폼 규칙을 참조하시기 바랍니다.
-
에디터에서 컴파일(Compile) 을 선택해 코드를 핫 리로드(Hot reload) 합니다.
(w:482 h:336 convert:false)
문 스태틱 메시 구성하기
DoorFrame 과 Door 스태틱 메시 컴포넌트를 시각적으로 나타낼 스태틱 메시 에셋을 구성해야 합니다.
-
콘텐츠 브라우저에서 C++ 클래스 폴더 로 이동합니다.
-
DoorActor 클래스를 우클릭한 다음 Door Actor를 바탕으로 블루프린트 클래스 생성(Create Blueprint Class based on Door Actor) 을 선택하고 블루프린트 액터의 이름을 Bp_DoorActor 로 설정합니다.
-
컴포넌트(Components) 탭에서 DoorFrame 스태틱 메시 컴포넌트를 선택합니다.
-
디테일(Details) 패널로 이동한 뒤 스태틱 메시를 SM_DoorFrame 으로 변경합니다.
(w:624 h:361 convert:false) -
컴포넌트 탭에서 DoorMesh 컴포넌트를 선택합니다. 디테일 패널로 이동한 뒤 스태틱 메시를 SM_Door 로 변경합니다.
(w:624 h:409 convert:false) -
그리고 트랜스폼(Transform) 카테고리에서 Y 위치(Y Location) 값을 45.0 으로 설정합니다.
(w:624 h:462 convert:false) -
저장(Save)을 클릭해 변경사항을 Bp_DoorActor에 저장합니다.
UCurveFloat와 타임라인 이벤트 트랙 만들기
타임라인 컴포넌트에는 키와 커브가 필요합니다. 각 커브에서는 시간과 값을 정의하는 키가 하나 이상 있습니다.커브는 키 사이를 보간해 타임라인의 특정 시점에 대한 값을 계산합니다.
이 예시에서는 UCurveFloat를 사용합니다.
-
DoorActor.h의ADoorActor클래스 정의로 이동한 뒤 다음 변수를 선언합니다.public: // 커브 에셋을 보관하는 변수 UPROPERTY(EditAnywhere) UCurveFloat* DoorTimelineFloatCurve; private: //업데이트 트랙 이벤트를 처리할 플로트 트랙 시그니처 FOnTimelineFloat UpdateFunctionFloat; //타임라인 그래프에 따라 문의 상대적 위치를 업데이트하는 함수 UFUNCTION() void UpdateTimelineComp(float Output); -
이제
DoorActor.cpp로 이동해UpdateTimelineComp메서드를 구현합니다.void ADoorActor::UpdateTimelineComp(float Output) { // 타임라인 커브(Timeline Curve)의 출력을 바탕으로 문의 새 상대적 위치 설정 및 구성 FRotator DoorNewRotation = FRotator(0.0f, Output, 0.f); Door->SetRelativeRotation(DoorNewRotation); } -
BeginPlay 메서드에 다음 코드를 추가합니다.
//플로트 트랙을 UpdateTimelineComp 함수의 출력에 바인딩 UpdateFunctionFloat.BindDynamic(this, &ADoorActor::UpdateTimelineComp); //플로트 커브가 있는 경우 그래프를 업데이트 함수에 바인딩 if (DoorTimelineFloatCurve) { DoorTimelineComp->AddInterpFloat(DoorTimelineFloatCurve, UpdateFunctionFloat); }
작업 중인 코드
DoorActor.h
// Copyright 1998-2021 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/TimelineComponent.h"
#include "DoorActor.generated.h"
UCLASS()
class TIMELINEDOORACTOR_API ADoorActor : public AActor
{
GENERATED_BODY()
public:
// 이 액터 프로퍼티의 디폴트값 설정
ADoorActor();
/* 커브 에셋을 보관하는 변수* /
UPROPERTY(EditAnywhere)
UCurveFloat* DoorTimelineFloatCurve;
protected:
// 게임 시작 시 또는 스폰 시 호출
virtual void BeginPlay() override;
//Door 에셋을 나타내는 MeshComponents
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UStaticMeshComponent* DoorFrame;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UStaticMeshComponent* Door;
//Door 메시를 애니메이트하는 TimelineComponent
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UTimelineComponent* DoorTimelineComp;
//근접성 볼륨으로 사용할 BoxComponent
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UBoxComponent* DoorProxVolume;
//업데이트 트랙 이벤트를 처리할 플로트 트랙 시그니처
FOnTimelineFloat UpdateFunctionFloat;
//타임라인 그래프에 따라 문의 상대적 위치를 업데이트하는 함수
UFUNCTION()
void UpdateTimelineComp(float Output);
public:
// 모든 프레임에서 호출
virtual void Tick(float DeltaTime) override;
};
DoorActor.cpp
//Copyright 1998-2021 Epic Games, Inc. All Rights Reserved.
#include "DoorActor.h"
#include "Components/BoxComponent.h"
// 디폴트 값 설정
ADoorActor::ADoorActor()
{
// 이 액터가 프레임마다 틱()을 호출하도록 설정. 필요하지 않다면 퍼포먼스 향상을 위해 이 기능을 끌 수 있습니다.
PrimaryActorTick.bCanEverTick = true;
//디폴트 컴포넌트 생성
DoorFrame = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorFrameMesh"));
Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));
DoorTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("DoorTimelineComp"));
DoorProxVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("DoorProximityVolume"));
//어태치먼트 구성
DoorFrame->SetupAttachment(RootComponent);
Door->AttachToComponent(DoorFrame,FAttachmentTransformRules::KeepRelativeTransform);
DoorProxVolume->AttachToComponent(DoorFrame, FAttachmentTransformRules::KeepRelativeTransform);
}
// 게임 시작 시 또는 스폰 시 호출
void ADoorActor::BeginPlay()
{
Super::BeginPlay();
//플로트 트랙을 UpdateTimelineComp 함수의 출력에 바인딩
UpdateFunctionFloat.BindDynamic(this, &ADoorActor::UpdateTimelineComp);
//플로트 커브가 있는 경우 그래프를 업데이트 함수에 바인딩
if (DoorTimelineFloatCurve)
{
DoorTimelineComp->AddInterpFloat(DoorTimelineFloatCurve, UpdateFunctionFloat);
}
}
void ADoorActor::UpdateTimelineComp(float Output)
{
// 타임라인 커브(Timeline Curve)의 출력을 바탕으로 문의 새로운 상대적 위치 설정 및 구성
FRotator DoorNewRotation = FRotator(0.0f,Output,0.f);
Door->SetRelativeRotation(DoorNewRotation);
}
// 모든 프레임에서 호출
void ADoorActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
콜리전 오버랩 이벤트 생성 및 바인딩
박스 컴포넌트는 액터가 콜리전 바운드를 드나들 때 반응해야 합니다.
-
TimelineDoorActor.h파일의 클래스 정의로 이동한 뒤 다음을 선언합니다.// DoorProxVolume의 오버랩 이벤트 시작 및 종료 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); -
DoorActor.cpp파일로 이동해OnOverlapBegin및OnOverlapEnd클래스 메서드를 구현합니다.void ADoorActor::OnOverlapBegin(UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { DoorTimelineComp->Play(); } void ADoorActor::OnOverlapEnd(UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex) { DoorTimelineComp->Reverse(); } -
아래와 같이 오버랩 함수를 BeginPlay 메서드에 바인딩합니다.
//근접성 박스(Proximity Box) 컴포넌트를 오버랩 함수에 바인딩 DoorProxVolume->OnComponentBeginOverlap.AddDynamic(this, &ADoorActor::OnOverlapBegin); DoorProxVolume->OnComponentEndOverlap.AddDynamic(this, &ADoorActor::OnOverlapEnd); -
코드를 컴파일합니다.
언리얼 에디터에서 커브 에셋 생성
언리얼 에디터에서 타임라인 액터(Timeline Actor) 블루프린트에 할당할 커브 에셋을 생성해야 합니다.
-
콘텐츠 브라우저(Content Browser) 에서 추가/임포트(Add/Import) > 기타(Miscellaneous) > 커브(Curve) 를 선택합니다.
(w:294 h:536 convert:false) -
CurveFloat 를 선택하고 CurveFloat 에셋의 이름을 DoorCurveFloat 로 지정합니다.
-
DoorCurveFloat 에셋을 더블클릭해 타임라인 에디터(Timeline Editor) 를 엽니다.
-
플로트 커브(Float Curve)에 두 개의 키를 추가하고 시간 값을 각각 (0,0), (4,90)으로 설정합니다.
(w:624 h:410 convert:false)
타임라인 커브 수정에 대한 자세한 내용은 키와 커브를 참조하시기 바랍니다.
-
시프트(Shift) 키를 누른 상태로 두 키를 함께 선택한 다음 자동(Auto) 큐브형(Cubic) 보간으로 설정하고 커브를 저장합니다.
(w:624 h:514 convert:false) -
Bp_DoorActor를 열고 컴포넌트 탭에서 Bp_DoorActor를 선택합니다.
-
디테일(Details) 패널에서 Door Timeline Float Curve 드롭다운 메뉴의 DoorCurveFloat를 선택합니다.
(w:624 h:536 convert:false) -
레벨 에디터에서 씬에 Bp_DoorActor를 배치합니다.
-
컴파일하고 저장한 다음 PIE를 누릅니다.
(w:624 h:350 convert:false)
입력 WASD를 이용해 관중 폰을 컨트롤할 수 있습니다. DoorActor의 콜리전 바운드로 들어가면 타임라인이 재생되고, 바운드를 나가면 타임라인이 거꾸로 재생됩니다.
완료된 코드
DoorActor.h
// Copyright 1998-2021 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/TimelineComponent.h"
#include "DoorActor.generated.h"
UCLASS()
class TIMELINEDOORACTOR_API ADoorActor : public AActor
{
GENERATED_BODY()
public:
// 이 액터 프로퍼티의 디폴트값 설정
ADoorActor();
//커브 에셋을 보관하는 변수
UPROPERTY(EditAnywhere)
UCurveFloat* DoorTimelineFloatCurve;
protected:
// 게임 시작 시 또는 스폰 시 호출
virtual void BeginPlay() override;
/*Door 에셋을 나타내는 MeshComponents*/
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UStaticMeshComponent* DoorFrame;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UStaticMeshComponent* Door;
//Door 메시를 애니메이트하는 TimelineComponent
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UTimelineComponent* DoorTimelineComp;
//근접성 볼륨으로 사용할 BoxComponent
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UBoxComponent* DoorProxVolume;
//업데이트 트랙 이벤트를 처리할 플로트 트랙 시그니처
FOnTimelineFloat UpdateFunctionFloat;
//타임라인 그래프에 따라 문의 상대적 위치를 업데이트하는 함수
UFUNCTION()
void UpdateTimelineComp(float Output);
/*DoorProxVolume의 오버랩 이벤트 시작 및 종료* /
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);
public:
// 모든 프레임에서 호출
virtual void Tick(float DeltaTime) override;
};
DoorActor.cpp
// Copyright 1998-2021 Epic Games, Inc. All Rights Reserved.
#include "DoorActor.h"
#include "Components/BoxComponent.h"
// 디폴트 값 설정
ADoorActor::ADoorActor()
{
// 이 액터가 프레임마다 틱()을 호출하도록 설정. 필요하지 않다면 퍼포먼스 향상을 위해 이 기능을 끌 수 있습니다.
PrimaryActorTick.bCanEverTick = true;
//디폴트 컴포넌트 생성
DoorFrame = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorFrameMesh"));
Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));
DoorTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("DoorTimelineComp"));
DoorProxVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("DoorProximityVolume"));
//어태치먼트 구성
DoorFrame->SetupAttachment(RootComponent);
Door->AttachToComponent(DoorFrame,FAttachmentTransformRules::KeepRelativeTransform);
DoorProxVolume->AttachToComponent(DoorFrame, FAttachmentTransformRules::KeepRelativeTransform);
}
// 게임 시작 시 또는 스폰 시 호출
void ADoorActor::BeginPlay()
{
Super::BeginPlay();
UpdateFunctionFloat.BindDynamic(this, &ADoorActor::UpdateTimelineComp);
//플로트 커브가 있는 경우 그래프를 업데이트 함수에 바인딩
if (DoorTimelineFloatCurve)
{
DoorTimelineComp->AddInterpFloat(DoorTimelineFloatCurve, UpdateFunctionFloat);
}
//근접성 박스(Proximity Box) 컴포넌트를 오버랩 함수에 바인딩
DoorProxVolume->OnComponentBeginOverlap.AddDynamic(this, &ADoorActor::OnOverlapBegin);
DoorProxVolume->OnComponentEndOverlap.AddDynamic(this, &ADoorActor::OnOverlapEnd);
}
void ADoorActor::UpdateTimelineComp(float Output)
{
FRotator DoorNewRotation = FRotator(0.0f,Output,0.f);
Door->SetRelativeRotation(DoorNewRotation);
}
void ADoorActor::OnOverlapBegin(UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
{
DoorTimelineComp->Play();
}
void ADoorActor::OnOverlapEnd(UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex)
{
DoorTimelineComp->Reverse();
}
// 모든 프레임에서 호출
void ADoorActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}