충돌(Collision)의 가장 기본적인 방법은 두 물체의 바운딩 박스(Bounding Box)를 비교하는 것이다. 바운딩 박스란 물체를 둘러싸는 사각형 영역을 의미한다. 이 방법은 빠르고 간단하지만, 물체의 모양에 대한 정확한 충돌 검사는 수행하지 않는다.

 

목차

     

     


     

     

    Trigger

     

    충돌(Collision)의 가장 기본적인 방법은 두 물체의 바운딩 박스(Bounding Box)를 비교하는 것이다. 바운딩 박스란 물체를 둘러싸는 사각형 영역을 의미한다. 이 방법은 빠르고 간단하지만, 물체의 모양에 대한 정확한 충돌 검사는 수행하지 않는다.

     

    보다 정확한 충돌 검사를 위해서는, 물체의 형태를 고려한 검사가 필요하다. 이를 위해 언리얼 C++에서는 물체의 형태를 기하학적인 도형으로 표현할 수 있는 Collision Shape을 사용한다. Collision Shape은 물체의 모양과 크기를 정확히 나타내기 위해 사용된다.

    언리얼 C++에서는 다양한 Collision Shape을 제공한다. 가장 간단한 방법은 Sphere Collision Shape을 사용하는 것이다. Sphere Collision Shape은 구 형태의 충돌 모델을 사용한다. 이 방법은 빠르고 간단하지만, 물체의 모양을 구 형태로 근사하는 것이 필요하다.

    보다 정확한 충돌 검사를 위해서는, 복잡한 형태의 Collision Shape을 사용할 수 있다. 언리얼 C++에서는 Box, Capsule, Convex Hull, Mesh 등 다양한 Collision Shape을 제공한다.

    충돌 검사를 수행하고 나면, 충돌한 물체의 위치와 방향, 속도 등을 계산할 수 있다. 이를 바탕으로 충돌한 물체에 대한 반응을 구현할 수 있다. 이를 위해서는 충돌 응답(Collision Response) 코드를 작성해야 한다. 충돌 응답 코드는 충돌한 물체가 서로 어떻게 반응해야 하는지를 결정하는 것이다. 예를 들어, 물체가 서로 충돌하면 반대 방향으로 튕겨져 나가거나, 속도가 감소하는 등의 반응을 구현할 수 있다.

     

    01_Spawn
      C01_Properties.h .cpp
    C02_Mesh
    C02_Mesh_Sphere
    C02_Mesh_Cone
    C03_Spawner.h .cpp
    02_Profiler
      C01_Log.h .cpp
    C02_DrawDebug.h .cpp
    03_Collision
      C01_ActorOverlap.h .cpp
    C02_ComponentOverlap.h .cpp 
    C03_OverlapAndHit.h .cpp 
    C04_Trigger.h .cpp 
    C04_Light.h .cpp 
    C05_MultiTrigger.h .cpp 생성
    C05_FallingBox.h .cpp 생성
    C05_SpotLight.h .cpp 생성
    C06_EventTrigger.h .cpp 생성
    C06_Explosion.h .cpp 생성

    Utilities
      CHelpers.h
     
    CAnimInstance.h .cpp
    CGameMode.h .cpp
    CPlayer.h .cpp

     

     

     


     

    C04_Trigger

     

    C04_Trigger.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C04_Trigger.generated.h"
    
    DECLARE_DELEGATE(FBoxLightOverlap); //void func_name()
    DECLARE_DELEGATE_RetVal_OneParam(FString, FBoxLightColorOverlap, FLinearColor);
    
    UCLASS()
    class U2212_03_API AC04_Trigger : public AActor
    {
    	GENERATED_BODY()
    	
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleAnywhere)
    		class UBoxComponent* Box;
    
    	UPROPERTY(VisibleAnywhere)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC04_Trigger();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
    
    	UFUNCTION()
    		void OnComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
    
    public:
    	FBoxLightOverlap OnBoxLightBeginOverlap; //이벤트 변수
    	FBoxLightOverlap OnBoxLightEndOverlap;   //이벤트 변수
    
    	FBoxLightColorOverlap OnBoxLightColorOverlap;
    };

     

     

    C04_Trigger.cpp

    더보기
    #include "03_Collision/C04_Trigger.h"
    #include "Global.h"
    #include "Components/BoxComponent.h"
    #include "Components/TextRenderComponent.h"
    
    AC04_Trigger::AC04_Trigger()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
    
    	CreateTextRender();
    
    	Box->bHiddenInGame = false;
    	Box->SetRelativeScale3D(FVector(3));
    }
    
    void AC04_Trigger::BeginPlay()
    {
    	Super::BeginPlay();
    	
    	Box->OnComponentBeginOverlap.AddDynamic(this, &AC04_Trigger::OnComponentBeginOverlap);
    	Box->OnComponentEndOverlap.AddDynamic(this, &AC04_Trigger::OnComponentEndOverlap);
    }
    
    void AC04_Trigger::OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
    {
    	if (OnBoxLightBeginOverlap.IsBound())
    		OnBoxLightBeginOverlap.Execute();
    
    	if (OnBoxLightBeginOverlap.IsBound())
    	{
    		FString str = OnBoxLightColorOverlap.Execute(FLinearColor::MakeRandomColor());
    
    		CLog::Print(str);
    	}
    
    
    }
    
    void AC04_Trigger::OnComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
    {
    	if (OnBoxLightEndOverlap.IsBound())
    		OnBoxLightEndOverlap.Execute();
    }

     

     


     

    C04_Light

     

    C04_Light.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C04_Light.generated.h"
    
    UCLASS()
    class U2212_03_API AC04_Light : public AActor
    {
    	GENERATED_BODY()
    	
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleAnywhere)
    		class UPointLightComponent* PointLight;
    
    	UPROPERTY(VisibleAnywhere)
    		class UPointLightComponent* PointLight2;
    
    	UPROPERTY(VisibleAnywhere)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC04_Light();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnLight();
    
    	UFUNCTION()
    		void OffLight();
    
    	UFUNCTION()
    		FString OnRandomColor(FLinearColor InColor);
    };

     

     

    C04_Light.cpp

    더보기
    #include "03_Collision/C04_Light.h"
    #include "Global.h"
    #include "C04_Trigger.h"
    #include "Components/PointLightComponent.h"
    #include "Components/TextRenderComponent.h"
    
    AC04_Light::AC04_Light()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UPointLightComponent>(this, &PointLight, "PointLight", Root);
    	CHelpers::CreateComponent<UPointLightComponent>(this, &PointLight2, "PointLight2", Root);
    
    	CreateTextRender();
    
    
    	PointLight->SetRelativeLocation(FVector(0, -50, 0));//Actor로부터의 상대간격
    	PointLight->LightColor = FColor::Red;
    	PointLight->Intensity = 1e+4f; //1 * 10 ^ 4
    	PointLight->AttenuationRadius = 200; //감쇄 반경
    
    	PointLight2->SetRelativeLocation(FVector(0, +50, 0));
    	PointLight2->LightColor = FColor::Red;
    	PointLight2->Intensity = 1e+4f; //1 * 10 ^ 4
    	PointLight2->AttenuationRadius = 200; //감쇄 반경
    }
    
    void AC04_Light::BeginPlay()
    {
    	Super::BeginPlay();
    	
    	//for (AActor* actor : GetWorld()->GetCurrentLevel()->Actors)
    	//{
    	//	if (!!actor && actor->IsA<AC04_Trigger>())
    	//		CLog::Log(actor->GetName());
    	//}
    
    	OffLight();
    
    
    	AC04_Trigger* trigger = CHelpers::FindActor<AC04_Trigger>(GetWorld());
    	CheckNull(trigger);
    
    	trigger->OnBoxLightBeginOverlap.BindUFunction(this, "OnLight");
    	trigger->OnBoxLightEndOverlap.BindUFunction(this, "OffLight");
    
    	trigger->OnBoxLightColorOverlap.BindUFunction(this, "OnRandomColor");
    }
    
    void AC04_Light::OnLight()
    {
    	PointLight->SetVisibility(true);
    }
    
    void AC04_Light::OffLight()
    {
    	PointLight->SetVisibility(false);
    	PointLight2->SetVisibility(false);
    }
    
    FString AC04_Light::OnRandomColor(FLinearColor InColor)
    {
    	PointLight2->SetVisibility(true);
    	PointLight2->SetLightColor(InColor);
    
    	return "Color : " + InColor.ToString();
    }

     


     

    실행화면

     

    왼쪽 빛은 Red로 오른쪽 빛은 Random하게 출력된다.

     


     

     

     

    MultiTrigger & Falling Box

     

     


     

    C05_MultiTrigger

     

    C05_MultiTrigger.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C05_MultiTrigger.generated.h"
    
    //Multicast의 경우 Event와 RetVal를 동시에 사용할 수 없다.
    DECLARE_MULTICAST_DELEGATE_TwoParams(FMultiLightOverlap, int32, FLinearColor);
    
    UCLASS()
    class U2212_03_API AC05_MultiTrigger : public AActor
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleAnywhere)
    		class UBoxComponent* Box;
    
    	UPROPERTY(VisibleAnywhere)
    		class UTextRenderComponent* Text;
    	
    public:	
    	AC05_MultiTrigger();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
    
    public:
    	FMultiLightOverlap OnMultiLightOverlap;
    };

    DECLARE_MULTICAST_DELEGATE_TwoParams(FMultiLightOverlapint32FLinearColor);

    • Multicast의 경우 Event와 RetVal를 사용할 수 없다.

     

     

    C05_MultiTrigger.cpp

    더보기
    #include "03_Collision/C05_MultiTrigger.h"
    #include "Global.h"
    #include "Components/BoxComponent.h"
    #include "Components/TextRenderComponent.h"
    
    AC05_MultiTrigger::AC05_MultiTrigger()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
    
    	CreateTextRender();
    
    	Box->bHiddenInGame = false;
    	Box->SetRelativeScale3D(FVector(3));
    
    }
    
    void AC05_MultiTrigger::BeginPlay()
    {
    	Super::BeginPlay();
    
    	Box->OnComponentBeginOverlap.AddDynamic(this, &AC05_MultiTrigger::OnComponentBeginOverlap);
    }
    
    void AC05_MultiTrigger::OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
    {
    	CheckFalse(OnMultiLightOverlap.IsBound());
    
    	int32 index = UKismetMathLibrary::RandomIntegerInRange(0, 2); //Global.h 내에 KismetMathLibrary가 있다.
    	FLinearColor color = FLinearColor::MakeRandomColor();
    
    	OnMultiLightOverlap.Broadcast(index, color);//Multicast를 사용할 때 Broadcast 사용.
    	
    }

    OnMultiLightOverlap.Broadcast(index, color)

    • Multicast를 사용할 때 Broadcast를 사용한다.
    • 반면에 Singlecast를 사용할 때는 Unitcast를 사용한다. 여기서는 Multicast로 만들었기 때문에 사용할 수 없다.

     


     

    C05_FallingBox

     

    C05_FallingBox.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C05_FallingBox.generated.h"
    
    UCLASS()
    class U2212_03_API AC05_FallingBox : public AActor
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UStaticMeshComponent* Meshes[3];//Static Mesh 3개 배열로 생성
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC05_FallingBox();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnPhysics(int32 InIndex, FLinearColor InColor);
    
    private:
    	class UMaterialInstanceDynamic* Materials[3]; //Material
    	FVector WorldLocation[3]; //최초 위치 기록
    
    };

     

     

    C05_FallingBox.cpp

    더보기
    #include "03_Collision/C05_FallingBox.h"
    #include "Global.h"
    #include "C05_MultiTrigger.h"
    #include "Components/StaticMeshComponent.h"
    #include "Components/TextRenderComponent.h"
    #include "Materials/MaterialInstanceConstant.h"
    #include "Materials/MaterialInstanceDynamic.h"
    
    AC05_FallingBox::AC05_FallingBox()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    
    	UStaticMesh* mesh;
    	CHelpers::GetAsset<UStaticMesh>(&mesh, "StaticMesh'/Game/Meshes/Cube.Cube'");
    
    	for(int32 i = 0; i<3; i++)
    	{
    		FString str;
    		str.Append("Meshes");
    		str.Append(FString::FromInt(i + 1));
    
    		CHelpers::CreateComponent<UStaticMeshComponent>(this, &Meshes[i], FName(str), Root);
    
    		Meshes[i]->SetRelativeLocation(FVector(0, i * 150, 0));
    		Meshes[i]->SetStaticMesh(mesh);
    		Meshes[i]->SetSimulatePhysics(true);
    	}
    
    	CreateTextRender();
    }
    
    void AC05_FallingBox::BeginPlay()
    {
    	Super::BeginPlay();
    
    	UMaterialInstanceConstant* material;
    	CHelpers::GetAssetDynamic<UMaterialInstanceConstant>(&material, "MaterialInstanceConstant'/Game/Materials/M_White_Inst.M_White_Inst'");
    
    	for (int32 i = 0; i < 3; i++)
    	{
    		Materials[i] = UMaterialInstanceDynamic::Create(material, this);
    		Materials[i]->SetVectorParameterValue("Color", FLinearColor::White);
    
    		Meshes[i]->SetMaterial(0, Materials[i]);
    		Meshes[i]->SetSimulatePhysics(false);
    
    		FTransform transform = Meshes[i]->GetComponentToWorld();
    		WorldLocation[i] = transform.GetLocation();
    	}
    
    	AC05_MultiTrigger* trigger = CHelpers::FindActor<AC05_MultiTrigger>(GetWorld());
    	CheckNull(trigger);
    
    	trigger->OnMultiLightOverlap.AddUFunction(this, "OnPhysics");
    	trigger->OnMultiLightOverlap.Broadcast(0, FLinearColor::Red);
    	
    }
    
    void AC05_FallingBox::OnPhysics(int32 InIndex, FLinearColor InColor)
    {
    	for (int32 i = 0; i < 3; i++)
    	{
    		Materials[i]->SetVectorParameterValue("Color", FLinearColor::White);
    		Meshes[i]->SetSimulatePhysics(false);
    		Meshes[i]->SetWorldLocation(WorldLocation[i]);
    	}
    
    	//InIndex로 받은 mesh만 Red 색과 피직스 적용.
    	Materials[InIndex]->SetVectorParameterValue("Color", FLinearColor::Red);
    	Meshes[InIndex]->SetSimulatePhysics(true);
    }

     

     

     

    • Clear: 연결된 것 전체 제거
    • Remove: 하나씩 제거
    • RemoveAll: 객체를 줘서 제거. Clear와 유사하다.

     

     

    이벤트

    여러 함수에 바인딩하여 모두 한 번에 실행시킬 수 있는 델리게이트이다.

     

    언리얼 공식문서 (한국어/영어)

    https://docs.unrealengine.com/4.27/ko/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Delegates/Events/

     

    https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Delegates/Events/

     

     


     

    실행화면

     

     


     

    C05_SpotLight

     

    C05_SpotLight.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C05_SpotLight.generated.h"
    
    UCLASS()
    class U2212_03_API AC05_SpotLight : public AActor
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class USpotLightComponent* Lights[3]; //Light 3개 생성
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC05_SpotLight();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnLight(int32 InIndex, FLinearColor InColor);
    };

     

     

    C05_SpotLight.cpp

    더보기
    #include "03_Collision/C05_SpotLight.h"
    #include "Global.h"
    #include "C05_MultiTrigger.h"
    #include "Components/SpotLightComponent.h"
    #include "Components/TextRenderComponent.h"
    
    AC05_SpotLight::AC05_SpotLight()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    
    	for (int32 i = 0; i < 3; i++)
    	{
    		FString str;
    		str.Append("Lights");
    		str.Append(FString::FromInt(i + 1));
    
    		CHelpers::CreateComponent<USpotLightComponent>(this, &Lights[i], FName(str), Root);
    
    		Lights[i]->SetRelativeLocation(FVector(0, i * 150, 0));
    		Lights[i]->SetRelativeRotation(FRotator(-90, 0, 0));//Pitch, Yaw, Roll 순서
    		Lights[i]->Intensity = 1e+5f;
    		Lights[i]->OuterConeAngle = 25;
    	}
    
    	CreateTextRender();
    }
    
    void AC05_SpotLight::BeginPlay()
    {
    	Super::BeginPlay();
    
    	AC05_MultiTrigger* trigger = CHelpers::FindActor<AC05_MultiTrigger>(GetWorld());
    	CheckNull(trigger);
    	                                                        
    	trigger->OnMultiLightOverlap.AddUFunction(this, "OnLight");
    }
    
    void AC05_SpotLight::OnLight(int32 InIndex, FLinearColor InColor)
    {
    	for (int32 i = 0; i < 3; i++)
    		Lights[i]->SetLightColor(FLinearColor::White);
    
    	Lights[InIndex]->SetLightColor(InColor);
    
    }

     

     


     

     

     

    Event Trigger & Explosion

     

     


     

    C06_EventTrigger

     

    C06_EventTrigger.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C06_EventTrigger.generated.h"
    
    UCLASS()
    class U2212_03_API AC06_EventTrigger : public AActor
    {
    	GENERATED_BODY()
    
    private:
    	DECLARE_EVENT_OneParam(AC06_EventTrigger, FExplosionEvent, int32);
    
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UBoxComponent* Box;
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC06_EventTrigger();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
    
    public:
    	FExplosionEvent OnExplosionEvent;
    
    };

     

     

    C06_EventTrigger.cpp

    더보기
    #include "03_Collision/C06_EventTrigger.h"
    #include "Global.h"
    #include "Components/BoxComponent.h"
    #include "Components/TextRenderComponent.h"
    
    AC06_EventTrigger::AC06_EventTrigger()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
    
    	CreateTextRender();
    
    	Box->SetRelativeScale3D(FVector(3));
    	Box->bHiddenInGame = false;
    }
    
    void AC06_EventTrigger::BeginPlay()
    {
    	Super::BeginPlay();
    
    	Box->OnComponentBeginOverlap.AddDynamic(this, &AC06_EventTrigger::OnComponentBeginOverlap);
    
    	
    }
    
    void AC06_EventTrigger::OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
    {
    	CheckFalse(OnExplosionEvent.IsBound());
    
    	int32 index = UKismetMathLibrary::RandomIntegerInRange(0, 2);
    
    	OnExplosionEvent.Broadcast(index);
    }

     

     

     

    C06_Explosion

     

    06_Explosion.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C06_Explosion.generated.h"
    
    UCLASS()
    class U2212_03_API AC06_Explosion : public AActor
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditAnywhere, Category = "Particles")
    		class UParticleSystem* Particles[3];
    
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC06_Explosion();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnExplosion(int32 InIndex);
    };

     

     

    06_Explosion.cpp

    더보기
    #include "03_Collision/C06_Explosion.h"
    #include "Global.h"
    #include "C06_EventTrigger.h" //trigger를 가져다가 쓰기 위해 헤더 추가
    #include "Particles/ParticleSystem.h"
    #include "Components/TextRenderComponent.h"
    
    AC06_Explosion::AC06_Explosion()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    
    	CreateTextRender();
    
    
    	CHelpers::GetAsset<UParticleSystem>(&Particles[0], "ParticleSystem'/Game/AdvancedMagicFX12/particles/P_ky_hit.P_ky_hit'");
    	CHelpers::GetAsset<UParticleSystem>(&Particles[1], "ParticleSystem'/Game/AdvancedMagicFX12/particles/P_ky_hit_dark.P_ky_hit_dark'");
    	CHelpers::GetAsset<UParticleSystem>(&Particles[2], "ParticleSystem'/Game/AdvancedMagicFX12/particles/P_ky_hit_fire.P_ky_hit_fire'");
    }
    
    void AC06_Explosion::BeginPlay()
    {
    	Super::BeginPlay();
    
    	//trigger를 연결해준다.
    	AC06_EventTrigger* trigger = CHelpers::FindActor<AC06_EventTrigger>(GetWorld());
    	CheckNull(trigger);
    
    	trigger->OnExplosionEvent.AddUFunction(this, "OnExplosion");
    	trigger->OnExplosionEvent.Broadcast(0);
    }
    
    void AC06_Explosion::OnExplosion(int32 InIndex)
    {
    	//Global.h 내의 Kismet/GameplayStatics.h를 사용.
    	//BP에서는 World가 자동으로 들어가지만 UnrealC++에서는 자동으로 들어가지 않기 때문에 GetWorld()를 넣어주어야 한다.
    	//Particles에 들어온 번호(InIndex)를 플레이시킨다.
    	UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), Particles[InIndex], GetActorLocation());
    }

     

     


     

     

    실행화면