본문 바로가기
Study/Unreal

[Unreal/정리] 카메라 쉐이크 / 트리거

by generous_jeans 2020. 11. 13.

- 카메라 쉐이크 -

// 플레이어가 맞을 때 카메라가 흔들리는 것. 

// 언리얼에서는 카메라 쉐이크 기능을 제공해주고 있음.

 

(언리얼 에디터) Player -> 우클릭_블루프린트 클래스 -> 부모 : "CameraShake" 이름 : "BPCameraShake"

 

// 디테일-Camera Shake-Single Instance : 하나만 처리.

// 디테일-Oscillation-Oscillation Duration : 진동 시간.

// 디테일-Oscillation-Rot Oscillation : 카메라를 회전시키는 진동.

// 디테일-Oscillation-Loc Oscillation: 카메라 위치를 전환시키는 진동.

// Amplitude : 진동폭(강도).

// Frequency : 진동 속도.

// 디테일-Oscillation-FOCOscillation : 카메라 시야각이 좁혀졌다가 늘어남. 지진같은 거를 만들 때 사용하기 좋음. 

 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 : "CameraShake" 이름 : "HitCameraShake"

 

(C++-HitCameraShake.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "Camera/CameraShake.h"
#include "HitCameraShake.generated.h"


UCLASS()
class UE7PROJECT_API UHitCameraShake : public UCameraShake
{
    GENERATED_BODY()
	
public:
    UHitCameraShake();
    
};

(C++-HitCameraShake.cpp)

// Fill out your copyright notice in the Description page of Project Settings.

#include "HitCameraShake.h"

UHitCameraShake::UHitCameraShake()
{
    OscillationDuration = 0.5f;
    
    // y축 기반으로 흔들리도록 설정. 
    LocOscillation.Y.Amplitude = 1.f;
    LocOscillation.Y.Frequency = 100.f;
    
    // z축 기반으로 흔들리도록 설정. 
    LocOscillation.Z.Amplitude = 1.f;
    LocOscillation.Z.Frequency = 100.f;
    
    // 시야각 기반으로 흔들리도록 설정. 
    /*FOVOscillation.Amplitude = 1.f;
    FOVOscillation.Frequency = 100.f;*/
    
    bSingleInstance = true;
    UHitCameraShake()    
    // 랜덤 오프셋을 사용하면 좀 더 자연스럽게 처리가 됨. 
    // SingleInstance를 false로 처리하면 이상하게 나옴. 따라서 true로 처리. 
    
    UHitCameraShake()    
}

 

(C++-PlayerCharacter.cpp)

...
float APlayerCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    float fDamage = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);

    CharacterState.iHP -= (int32)DamageAmount;

    if (CharacterState.iHP < 0)
    {
        CharacterState.iHP = 0;
    }

    AMainGameMode* GameMode = Cast<AMainGameMode>(GetWorld()->GetAuthGameMode());

    if (IsValid(GameMode))
    {
        UMainHUDWidget* MainWidget = GameMode->GetMainHUDWidget();

        if (IsValid(MainWidget))
            MainWidget->SetPlayerHP(CharacterState.iHP / (float)CharacterState.iHPMax);
    }

    GetController<APlayerController>()->ClientPlayCameraShake(UHitCameraShake::StaticClass(), 1.f, ECameraAnimPlaySpace::CameraLocal);

    return fDamage; 
} 
...

 

 

- 조명 트리거 - 

// 방 안에 들어갔을 때 불이 켜진다거나 특정 지역에 도착했을 때 돌이 굴러떨어지는 등의 기능을 만드는 것.

// 비어 있는 액터를 사용. 충돌체를 만들고 충돌이 일어나면 효과가 나타나도 하는 형태로 진행됨.

 

(언리얼 에디터) 스포트 라이트 배치 

// 빛의 각도를 조절해서 사용할 수 있음.

 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 : "Actor" 이름 : "LightTrigger"

 

(C++-LightTrigger.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "GameFramework/Actor.h"
#include "LightTrigger.generated.h"

UCLASS()
class UE7PROJECT_API ALightTrigger : public AActor
{
    GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ALightTrigger();

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    class UBoxComponent* Box;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    AActor* Light;

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);
    
};

(C++-LightTrigger.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "LightTrigger.h"

// Sets default values
ALightTrigger::ALightTrigger()
{
    // 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"));

    Light = nullptr;
}

// Called when the game starts or when spawned
void ALightTrigger::BeginPlay()
{
    Super::BeginPlay();
	
    Box->OnComponentBeginOverlap.AddDynamic(this, &ALightTrigger::TriggerBeginOverlap);
    Box->OnComponentEndOverlap.AddDynamic(this, &ALightTrigger::TriggerEndOverlap);

    if (IsValid(Light))
        Light->GetRootComponent()->SetVisibility(false);
}

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

void ALightTrigger::TriggerBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    PrintViewport(1.f, FColor::Red, TEXT("Trigger"));

    if (IsValid(Light))
        Light->GetRootComponent()->SetVisibility(true);
}

void ALightTrigger::TriggerEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
    PrintViewport(1.f, FColor::Red, TEXT("TriggerEnd"));

    if (IsValid(Light))
        Light->GetRootComponent()->SetVisibility(false);
}

 

 

(언리얼 에디터) 세팅-프로젝트 세팅 -> 엔진-콜리전 -> Preset-Trigger : Player : 겹침 나머지 : 무시

 

(언리얼 에디터) LightTrigger 배치

(언리얼 에디터) LightTrigger -> 디테일 -> Light Trigger-Light : "SpotLight"

 

- 함정 트리거 - 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 : "Actor" 이름 : "SpawnTrigger"

 

(C++-SpawnTrigger.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "GameFramework/Actor.h"
#include "SpawnTrigger.generated.h"

UCLASS()
class UE7PROJECT_API ASpawnTrigger : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ASpawnTrigger();

protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
	class UBoxComponent* Box;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
	TSubclassOf<AActor>	SpawnClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
	AActor* SpawnPoint;

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);

};

(C++-SpawnTrigger.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "SpawnTrigger.h"

// Sets default values
ASpawnTrigger::ASpawnTrigger()
{
    // 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"));
}

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

    Box->OnComponentBeginOverlap.AddDynamic(this, &ASpawnTrigger::TriggerBeginOverlap);
    Box->OnComponentEndOverlap.AddDynamic(this, &ASpawnTrigger::TriggerEndOverlap);	
}

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

void ASpawnTrigger::TriggerBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    PrintViewport(1.f, FColor::Red, TEXT("Trigger"));

    if (IsValid(SpawnClass) && IsValid(SpawnPoint))
    {
        FActorSpawnParameters	params;
        params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;

        GetWorld()->SpawnActor<AActor>(SpawnClass, SpawnPoint->GetActorLocation(), SpawnPoint->GetActorRotation(), params);
        
        PrintViewport(1.f, FColor::Red, TEXT("Trigger"));
    }

    Destroy();  // 트리거를 한 번만 사용할 때는 Destroy()를 사용.
}

void ASpawnTrigger::TriggerEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
    PrintViewport(1.f, FColor::Red, TEXT("TriggerEnd"));
}

 

(언리얼 에디터) SpawnTrigger 배치

(언리얼 에디터) 기본 액터 배치 

(언리얼 에디터) SpawnTrigger -> 디테일 -> Spawn Trigger-Spawn Point : "Actor"

 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 : "Actor" 이름 : "DropObject"

 

(C++-DropObject.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "GameFramework/Actor.h"
#include "DropObject.generated.h"

UCLASS()
class UE7PROJECT_API ADropObject : public AActor
{
    GENERATED_BODY()
	
public:	
    // Sets default values for this actor's properties
    ADropObject();

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;

};

(C++-DropObject.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "DropObject.h"

// Sets default values
ADropObject::ADropObject()
{
    // 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("BlockAllDynamic"));
}

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

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

 

(언리얼 에디터) SpawnTrigger -> 디테일 -> Spawn Trigger-Spawn Class : "DropObject"

 

(언리얼 에디터) 새폴터 : "Object"

(언리얼 에디터) Object -> 우클릭_블루프린트 클래스 -> 부모 : "DropObejct" 이름 : "BPRock"

 

(언리얼 에디터-BPRock) Mesh -> 디테일-Static Mesh : 설정

(언리얼 에디터-BPRock) Box -> 디테일-콜리전-Simulation generates Hit Event : "체크"

 

(언리얼 에디터) SpawnTrigger -> 디테일 -> Spawn Trigger-Spawn Class : "BPRock"

 

댓글