트리거 클래스를 두가지로 구성하면 훨씬 다양한 기능을 연출할 수 있습니다.
1. 트리거 클래스
// TriggerBoxRock.h
#pragma once
#include "GameInfo.h"
#include "GameFramework/Actor.h"
#include "ObstacleRock.h"
#include "TriggerBoxRock.generated.h"
UCLASS()
class ESCAPEGAME_API ATriggerBoxRock : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATriggerBoxRock();
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
class UBoxComponent* Box;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
AObstacleRock* Rock;
bool bRollEnable;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
public:
UFUNCTION()
void TriggerBeginOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult);
UFUNCTION()
void TriggerEndOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex);
public:
void RollRock(float DeltaTime);
bool IsRoll();
};
// TriggerBoxRock.cpp
#include "TriggerBoxRock.h"
// Sets default values
ATriggerBoxRock::ATriggerBoxRock()
{
// 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;
Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Box"));
SetRootComponent(Box);
Box->SetCollisionProfileName(TEXT("Trigger"));
Rock = nullptr;
}
// Called when the game starts or when spawned
void ATriggerBoxRock::BeginPlay()
{
Super::BeginPlay();
// 델리게이트에 함수 등록
Box->OnComponentBeginOverlap.AddDynamic(this, &ATriggerBoxRock::TriggerBeginOverlap);
Box->OnComponentEndOverlap.AddDynamic(this, &ATriggerBoxRock::TriggerEndOverlap);
if (IsValid(Rock))
Rock->GetRootComponent()->SetVisibility(false);
}
// Called every frame
void ATriggerBoxRock::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (IsRoll())
{
RollRock(DeltaTime);
}
}
void ATriggerBoxRock::TriggerBeginOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
bRollEnable = true;
if (IsValid(Rock))
Rock->GetRootComponent()->SetVisibility(true);
}
void ATriggerBoxRock::TriggerEndOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex)
{
}
void ATriggerBoxRock::RollRock(float DeltaTime)
{
if (Rock->GetActorLocation().X > -1400) {
Rock->SetActorLocation(FVector(Rock->GetActorLocation().X - 1000 * DeltaTime, Rock->GetActorLocation().Y, Rock->GetActorLocation().Z));
Rock->AddActorLocalRotation(FRotator(DeltaTime * 250, 0.f, 0.f)); }
}
bool ATriggerBoxRock::IsRoll()
{
if (bRollEnable)
{
return true;
}
else
{
return false;
}
}
Box Component와 굴러올 돌의 액터를 가지고 있고, 델리게이트에 함수를 등록하고 오버랩 됐을 때, 호출할 함수를 정의해주면 됩니다.
굴러올 돌 액터는 UPROPERTY 형식으로 선언했으므로, 에디터상에서 편하게 설정해서 사용합니다.
2. 굴러올 돌 클래스
// ObstacleRock.h
#pragma once
#include "GameInfo.h"
#include "GameFramework/Actor.h"
#include "ObstacleRock.generated.h"
UCLASS()
class ESCAPEGAME_API AObstacleRock : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AObstacleRock();
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
class UBoxComponent* Box;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
class UStaticMeshComponent* Mesh;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
public:
UFUNCTION()
void TriggerBeginOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult);
UFUNCTION()
void TriggerEndOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex);
};
// ObstacleRock.cpp
#include "ObstacleRock.h"
#include "MyPlayerCharacter.h"
#include "MyPlayerController.h"
#include "CameraShakeObstacle.h"
// Sets default values
AObstacleRock::AObstacleRock()
{
// 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;
Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Box"));
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
SetRootComponent(Box);
Mesh->SetupAttachment(Box);
Mesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Box->SetSimulatePhysics(true);
Box->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
Box->SetCollisionProfileName(TEXT("Obstacle"));
}
// Called when the game starts or when spawned
void AObstacleRock::BeginPlay()
{
Super::BeginPlay();
Box->OnComponentBeginOverlap.AddDynamic(this, &AObstacleRock::TriggerBeginOverlap);
Box->OnComponentEndOverlap.AddDynamic(this, &AObstacleRock::TriggerEndOverlap);
}
// Called every frame
void AObstacleRock::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AObstacleRock::TriggerBeginOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
// 게임오버 시네마틱 영상 ON
PrintViewport(1.f, FColor::Green, "Death");
AMyPlayerController* pController = Cast<AMyPlayerController>(GetWorld()->GetFirstPlayerController());
if (IsValid(pController))
{
AMyPlayerCharacter* pCharacter = Cast<AMyPlayerCharacter>(pController->GetPawn());
if (IsValid(pCharacter))
{
pCharacter->GetController<AMyPlayerController>()->ClientPlayCameraShake(UCameraShakeObstacle::StaticClass(),
1.f, ECameraAnimPlaySpace::CameraLocal);
pCharacter->Death();
}
}
}
void AObstacleRock::TriggerEndOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex)
{
}
플레이어와 돌이 닿았을 때, 카메라쉐이크하고, 게임오버시킵니다.
대부분의 트리거가 디테일만 조금씩 다르지, 이러한 방식으로 동작합니다.
게임오버 영상은 생각해봐야하고, 카메라쉐이크는 다음 글에 자세히 정리하겠습니다.
'게임 개발 (언리얼 엔진)' 카테고리의 다른 글
UE4 게임 개발 EscapeGame - 7 : 카메라쉐이크(CameraShake) (0) | 2020.12.04 |
---|---|
UE4 게임 개발 EscapeGame - 6 : 디스트럭터블 메시(Destructible Mesh) (0) | 2020.12.01 |
UE4 게임 개발 EscapeGame - 4 : 트리거 활용 (0) | 2020.11.23 |
UE4 게임 개발 EscapeGame - 3 : TriggerBox와 BeginOverlap/EndOverlap (0) | 2020.11.12 |
UE4 게임 개발 EscapeGame - 2 : 캐릭터 및 게임모드 기본 세팅 (0) | 2020.11.05 |