언리얼 C++에서 충돌(Collision)을 다루기 위해서는, 먼저 충돌 검사(Collision Detection)를 해야 한다. 충돌 검사는 물체의 위치와 크기를 고려하여 두 물체가 서로 충돌했는지 여부를 판단하는 것이다. 언리얼 C++에서는 다양한 충돌 검사 방법을 제공한다.

 

목차

     

     


     

     

    Collision

     

    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 생성
    Utilities
      CHelpers.h
     
    CAnimInstance.h .cpp
    CGameMode.h .cpp
    CPlayer.h .cpp

     


     

    C02_Component Overlap 생성

     

    새 C++ 클래스 - C02_ComponentOverlap 생성

     

     

    C02_ComponentOverlap.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C02_ComponentOverlap.generated.h"
    
    UCLASS()
    class U2212_03_API AC02_ComponentOverlap : public AActor
    {
    	GENERATED_BODY()
    	
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleAnywhere)
    		class UBoxComponent* Box;
    
    	UPROPERTY(VisibleAnywhere)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC02_ComponentOverlap();
    
    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);
    };

     

     

    C02_ComponentOverlap.cpp

    더보기
    #include "03_Collision/C02_ComponentOverlap.h"
    #include "Global.h"
    #include "Components/BoxComponent.h"
    #include "Components/TextRenderComponent.h"
    
    AC02_ComponentOverlap::AC02_ComponentOverlap()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
    
    	CreateTextRender();
    
    	Box->bHiddenInGame = false;
    	Box->SetRelativeScale3D(FVector(3));
    }
    
    void AC02_ComponentOverlap::BeginPlay()
    {
    	Super::BeginPlay();
    	
    	Box->OnComponentBeginOverlap.AddDynamic(this, &AC02_ComponentOverlap::OnComponentBeginOverlap);
    	Box->OnComponentEndOverlap.AddDynamic(this, &AC02_ComponentOverlap::OnComponentEndOverlap);
    }
    
    void AC02_ComponentOverlap::OnComponentBeginOverlap(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
    {
    	FString str;
    
    	str = "-----Begin-----";
    	CLog::Log(str);
    
    	str = FString::Printf(L"Overlap Component : %s", *OverlappedComponent->GetName());
    	CLog::Log(str);
    
    	str = FString::Printf(L"Other Actor : %s", *OtherActor->GetName());
    	CLog::Log(str);
    
    	str = FString::Printf(L"Other Component : %s", *OtherComp->GetName());
    	CLog::Log(str);
    }
    
    void AC02_ComponentOverlap::OnComponentEndOverlap(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex)
    {
    	FString str;
    
    	str = "-----End-----";
    	CLog::Log(str);
    
    	str = FString::Printf(L"Overlap Component : %s", *OverlappedComponent->GetName());
    	CLog::Log(str);
    
    	str = FString::Printf(L"Other Actor : %s", *OtherActor->GetName());
    	CLog::Log(str);
    
    	str = FString::Printf(L"Other Component : %s", *OtherComp->GetName());
    	CLog::Log(str);
    }

     

    BlueprintAssignable: 이벤트를 블루프린트에 공개되게 하는 역할


     

    C03_Overlap And Hit 생성

     

    새 C++ 클래스 - C03_Overlap And Hit 생성

     

     

    C03_OverlapAndHit.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C03_OverlapAndHit.generated.h"
    
    UCLASS()
    class U2212_03_API AC03_OverlapAndHit : public AActor
    {
    	GENERATED_BODY()
    	
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleAnywhere)
    		class UBoxComponent* Box;
    
    	UPROPERTY(VisibleAnywhere)
    		class UTextRenderComponent* Text;
    
    public:	
    	AC03_OverlapAndHit();
    
    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);
    
    	UFUNCTION()
    		void OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
    };

     

     

    C03_OverlapAndHit.cpp

    더보기
    #include "03_Collision/C03_OverlapAndHit.h"
    #include "Global.h"
    #include "Components/BoxComponent.h"
    #include "Components/TextRenderComponent.h"
    
    AC03_OverlapAndHit::AC03_OverlapAndHit()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
    
    	CreateTextRender();
    
    	Box->bHiddenInGame = false;
    	Box->SetRelativeScale3D(FVector(3));
    }
    
    void AC03_OverlapAndHit::BeginPlay()
    {
    	Super::BeginPlay();
    
    	Box->OnComponentBeginOverlap.AddDynamic(this, &AC03_OverlapAndHit::OnComponentBeginOverlap);
    	Box->OnComponentEndOverlap.AddDynamic(this, &AC03_OverlapAndHit::OnComponentEndOverlap);
    	//Box->OnComponentHit.AddDynamic(this, &AC03_OverlapAndHit::OnComponentHit);
    }
    
    void AC03_OverlapAndHit::OnComponentBeginOverlap(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
    {
    	FString str;
    
    	str = FString::Printf(L"Begin Overlap : %s", *OtherActor->GetName());
    	CLog::Log(str);
    }
    
    void AC03_OverlapAndHit::OnComponentEndOverlap(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex)
    {
    	FString str;
    
    	str = FString::Printf(L"End Overlap : %s", *OtherActor->GetName());
    	CLog::Log(str);
    }
    
    void AC03_OverlapAndHit::OnComponentHit(UPrimitiveComponent * HitComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, FVector NormalImpulse, const FHitResult & Hit)
    {
    	FString str;
    
    	str = FString::Printf(L"Hit : %s", *OtherActor->GetName());
    	CLog::Log(str);
    }

     

     

    BP_C03_OverlapAndHit

    • 피직스-  Simulate Physics를 체크하여 큐브가 떨어지도록 설정한다.언리얼 4.25부터 받는쪽을 기준으로 Collision을 연산한다.

    • Query only: 겹침(overlap)연산만 수행
    • Physics only: 블록(block)연산만 수행
    • Collision Enable: 겹침, 블록연산 둘 다 수행

     

     

    실행화면

     

     

     


     

     

     

     

    Trigger Light

     

     

     


     

     

    Delegate

     

    결합성을 낮추는 방식으로 관리한다. 

     

    SOLID

     

    https://wkdtjsgur100.github.io/solid-principle/

     

    객체지향 디자인의 5원칙(SOLID 원칙)

    좋은 객체지향 설계를 위해서는 다음의 5가지 원칙을 따르는 것이 좋고, 다음의 원칙들을 기반으로 디자인 패턴이 되기 때문에,디자인 패턴을 공부하기 전에 알아두면 왜 그 패턴이 좋은 패턴인

    wkdtjsgur100.github.io

    https://www.nextree.co.kr/p6960/

     

    객체지향 개발 5대 원리: SOLID

    현재를 살아가는 우리들은 모두 일정한 원리/원칙 아래에서 생활하고 있습니다. 여기서의 원칙 이라 함은 좁은 의미로는 개개인의 사고방식이나 신념, 가치관 정도가 될 수가 있겠고, 넓게는 한

    www.nextree.co.kr

     

    https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Actors/ActorLifecycle/

     

    Actor Lifecycle

    What actually happens when an Actor is loaded or spawned, and eventually dies.

    docs.unrealengine.com


     

     

     

    CHelpers.h

     

    CHelpers.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    
    ...
    
    class U2212_03_API CHelpers
    {
    public:
    	...
    
    	template<typename T>
    	static T* FindActor(UWorld* InWorld)
    	{
    		for (AActor* actor : InWorld->GetCurrentLevel()->Actors)
    		{
    			if (!!actor && actor->IsA<T>())
    				return Cast<T>(actor);
    		}
    
    		return nullptr;
    	}
    
    	template<typename T>
    	static void FindActors(UWorld* InWorld, TArray<T*>& OutActors)
    	{
    		for (AActor* actor : GetWorld()->GetCurrentLevel()->Actors)
    		{
    			if (!!actor && actor->IsA<T>())
    				OutActors.Add(Cast<T>(actor));
    		}
    	}
    };

     

    C04_Light의 아래의 접힌 코드를 CHelpers.h에서

    • static void FindActor(UWorld* InWorld)
    • static void FindActors(UWorld* InWorld, TArray<T*>& OutActors)

    템플릿화 하였다.

    더보기
    for (AActor* actor : GetWorld()->GetCurrentLevel()->Actors)
    {
        if (!!actor && actor->IsA<AC04_Trigger>())
            CLog::Log(actor->GetName());
    }

     

     

     


     

     

     

     

     

    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()
    
    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;   //이벤트 변수
    };

     

     

    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();
    }
    
    void AC04_Trigger::OnComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
    {
    	if (OnBoxLightEndOverlap.IsBound())
    		OnBoxLightEndOverlap.Execute();
    }

     

     

     


     

    C04_Light 생성

     

     

    C04_Lightr.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();
    };

     

     

    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");
    }
    
    void AC04_Light::OnLight()
    {
    	PointLight->SetVisibility(true);
    }
    
    void AC04_Light::OffLight()
    {
    	PointLight->SetVisibility(false);
    	PointLight2->SetVisibility(false);
    }

     


     

     

    실행화면