이제까지 충돌할려는 것에서 트리거를 찾아서 등록을 했었는데. 이런 방식도 있다 라고 생각하면 될거 같다. 실제로 현업에서 사용하는 방법은 아니다. (비효율적)

새 클래스 생성 / 폴더 생성.

Untitled

C01_SphereTrace

DebugDraw 블프에서 사용하였을 때 None Foward, Duration 사용하는 것들이 있다. 이게 Enum형으로 되어있다. EDrawDebugTrace 라고 정의된다. 일반적으로 Enum 선언 방식이 2가지가 있다.

Unreal에서 이런식으로 공개된 결과형 Type이다.

//현재 방식
UENUM(BlueprintType)
enum class EDraw : uint8
{

};

만약에 이런식으로 정의하면. A는 프로그램 전역에서 Enum이 되버린다. 이걸 구역으로 묶는 방법이 있는데.

enum EDraw
{
	A = 0, B,
};

구역으로 묶는 법 (옛날 방식) - using namespace 는 자주 쓰인다.

//옛날 방식
using namespace EDraw
{
		enum Type
	{
		A = 0, B,
	};
}
/////////////////
//다른 곳에서 EDraw::A 이런식으로 쓴다. 

하필 옛날방식처럼 정의 되어 있는 것들이 있다. EDrawDebugTrace 들어가서 보면 언리얼 에서 Enum은 사이즈를 uint8 로 규정해줘야 한다.

Untitled

그래서 EDrawDebugTrace의 사이즈가 정의가 없는데. 이걸 블루프린트에 강제적으로 주는 방법이

Untitled

TEnumAsByte (템플릿) : 블프에 공개하려고 사이즈를 강제적으로 주는 방법. 이Enum은 byte를 사용하겠다고 명시해 주는 것

private:
	UPROPERTY(EditAnywhere)
		TEnumAsByte<EDrawDebugTrace::Type> DebugType; // Enum형 Byte강제

	UPROPERTY(EditAnywhere)
		float DrawDuration = 5; // 얼마 동안 돌릴 것인가.

	UPROPERTY(EditAnywhere)
		float ImpulseAmount = 550; //힘을 받는 범위 

언리얼에서 힙을 얘기 할 떄 (다른 곳에서도) Force.Impulse라고 있다.

force : 서로 부딪혔을 때 밀어내는 힘 주는 쪽이 Force, 충격을 받는 쪽이 Pulse ,

이 때 주의 할 점이, 주는 쪽이 force이고 날라가는것이 Impulse 인데 서버에서 구분 할때 주체가 달라지는데 , 힘을 받아서 날라가야하는데, 힘을 줘서 날라가니까. 다시 다른 쪽에 힘(force)을 주면, 가속이 일어난다, .또 만약에 서로 같은 force라면 상쇄가 일어난다. 그래서 force랑 Impulse를 항상 구분해서 사용해야 한다.

C01_SphereTrace.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Kismet/KismetSystemLibrary.h" //EDrawDebug 있는 곳
#include "C01_SphereTrace.generated.h"

UCLASS()
class U2110_03_API AC01_SphereTrace : public AActor
{
	GENERATED_BODY()
	
private:
	UPROPERTY(EditAnywhere)
		TEnumAsByte<EDrawDebugTrace::Type> DebugType; // Enum형 Byte강제

	UPROPERTY(EditAnywhere)
		float DrawDuration = 5; // 얼마 동안 돌릴 것인가.

	UPROPERTY(EditAnywhere)
		float ImpulseAmount = 550; 

private:
	UPROPERTY(VisibleDefaultsOnly)
		class UParticleSystemComponent* Particle;

public:	
	AC01_SphereTrace();

protected:
	virtual void BeginPlay() override;

public:
	UFUNCTION()
		void OnActorBeginOverlap(AActor* OverlappedActor, AActor* OtherActor);
};

현재 로써는 충돌체가 없다. 그래서 Trigger를 하나 만들어 줄 것

C01_SphereTrace.cpp

#include "C01_SphereTrace.h"
#include "Global.h"
#include "Particles/ParticleSystemComponent.h"

AC01_SphereTrace::AC01_SphereTrace()
{
	CHelpers::CreateComponent<UParticleSystemComponent>(this, &Particle, "Particle");

	UParticleSystem* particle;
	CHelpers::GetAsset<UParticleSystem>(&particle, "ParticleSystem'/Game/M5VFXVOL2/Particles/Explosion/Fire_Exp_00.Fire_Exp_00'");//particle 경로
	Particle->SetTemplate(particle); //파티클 지정해주는 것 
	Particle->bAutoActivate = false; //AitoActivate 자동실행 꺼주기 (그냥 바로 폭발 하고 끝나는 거 막기 위함) 
}

void AC01_SphereTrace::BeginPlay()
{
	Super::BeginPlay();
	
}

void AC01_SphereTrace::OnActorBeginOverlap(AActor* OverlappedActor, AActor* OtherActor)
{

}

실행 셋팅 Simulate Physics

Untitled

크기에 따라 질량이 달라진다.

Untitled

Untitled

Untitled

어디 구역 들어갔을 때 호출

Untitled

C01_Trigger 클래스 생성

C01_Trigger.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "C01_Trigger.generated.h"

UCLASS()
class U2110_03_API AC01_Trigger : public AActor
{
	GENERATED_BODY()

private:
	UPROPERTY(VisibleDefaultsOnly)
		class USceneComponent* Root;

	UPROPERTY(VisibleDefaultsOnly)
		class UBoxComponent* Box;

	UPROPERTY(VisibleDefaultsOnly)
		class UTextRenderComponent* Text;

public:	
	AC01_Trigger();

protected:
	virtual void BeginPlay() override;
};

C01_Trigger.cpp

#include "C01_Trigger.h"
#include "Global.h"
#include "C01_SphereTrace.h"
#include "Components/BoxComponent.h"
#include "Components/TextRenderComponent.h"

AC01_Trigger::AC01_Trigger()
{
	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
	CHelpers::CreateComponent<UTextRenderComponent>(this, &Text, "Text", Root);

	//충돌체
	Box->SetRelativeScale3D(FVector(3));
	Box->bHiddenInGame = false;

	Text->SetRelativeLocation(FVector(0, 0, 100));
	Text->SetRelativeRotation(FRotator(0, 180, 0));
	Text->SetRelativeScale3D(FVector(2));
	Text->TextRenderColor = FColor::Red;
	Text->HorizontalAlignment = EHorizTextAligment::EHTA_Center;
	Text->Text = FText::FromString(GetName().Replace(L"Default__", L""));

}

void AC01_Trigger::BeginPlay()
{
	Super::BeginPlay();
	
	//배치 되어있는 거 찾아오기
	AC01_SphereTrace* trace = CHelpers::FindActor<AC01_SphereTrace>(GetWorld());
	CheckNull(trace);

	OnActorBeginOverlap.AddDynamic(trace, &AC01_SphereTrace::OnActorBeginOverlap);
}

Box에 연결해둔 AC01_SphereTrace의 모양을 보면 OnActorBeginOverlap 해서 2개를 주었다. (OverlappedActor, OtherActor) 이게 결국 ActorOverlap과 같다.

void OnActorBeginOverlap(AActor* OverlappedActor, AActor* OtherActor);

OnActorBeginOverlap 에 들어가서 보면 앞에 3개 제외하고 뒤에 보면 똑같은 걸 볼 수 있다.

DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams( FActorBeginOverlapSignature, AActor, OnActorBeginOverlap, **AActor*, OverlappedActor, AActor*, OtherActor** );

이 말은 (AActor* OverlappedActor, AActor* OtherActor) 그냥 직접 Trace에 있는거 연결해도 된다는 것 , Trace객체 안에 있는. AC01_SphereTrace에 OnActorBeginOverlap 을 이방법은 자신의 델리게이트에 다른 것을 가져다 연결해준다. (관리 해주는데 있어. 좀..;;)

OnActorBeginOverlap.AddDynamic(trace, &AC01_SphereTrace::OnActorBeignOverlap);

액터 끼리 겹치면 OnActorBeginOverlap 이 발생한다.

Box->SetRelativeScale3D(FVector(3));
Box->bHiddenInGame = false;

C01_SphereTrace.cpp

#include "C01_SphereTrace.h"
#include "Global.h"
#include "Particles/ParticleSystemComponent.h"

AC01_SphereTrace::AC01_SphereTrace()
{

	CHelpers::CreateComponent<UParticleSystemComponent>(this, &Particle, "Particle");

	UParticleSystem* particle;
	CHelpers::GetAsset<UParticleSystem>(&particle, "ParticleSystem'/Game/M5VFXVOL2/Particles/Explosion/Fire_Exp_00.Fire_Exp_00'");//particle 경로
	Particle->SetTemplate(particle); //파티클 지정해주는 것 
	Particle->bAutoActivate = false; //AitoActivate 자동실행 꺼주기 (그냥 바로 폭발 하고 끝나는 거 막기 위함) 
}

void AC01_SphereTrace::BeginPlay()
{
	Super::BeginPlay();
	
}

void AC01_SphereTrace::OnActorBeginOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
	//위치
	FVector location = GetActorLocation();

	TArray<TEnumAsByte<EObjectTypeQuery>> types;
	types.Add(EObjectTypeQuery::ObjectTypeQuery4);

	TArray<AActor *> ignores;
	TArray<FHitResult> hitResults; //Hit결과를 배열로 넘겨오기 

	//하나라도 충돌 했다면, b가 True가 나올 것이다. 
	bool b = UKismetSystemLibrary::SphereTraceMultiForObjects(GetWorld(), location, location, 300, types, false, ignores, DebugType, hitResults, true, FLinearColor::Green, FLinearColor::Blue, DrawDuration);
	CheckFalse(b);

	//Particle Component ? 
	Particle->ResetParticles();
	Particle->SetActive(true);

	for (const FHitResult& hitResult : hitResults)
	{
		UStaticMeshComponent* mesh = Cast<UStaticMeshComponent> (hitResult.GetActor()->GetRootComponent());
		if (!!mesh && mesh->IsSimulatingPhysics())
			mesh->AddRadialImpulse(location, 1000, mesh->GetMass() * ImpulseAmount, ERadialImpulseFalloff::RIF_Linear);
	}

}
UKismetSystemLibrary

KismetSystemLibrary에 Trace 붙은 것이 있다. LightTrace, BoxTrace, SphereTrace등등 이런 것들이 World에 있는 것을 호출한다.

Untitled

UKismetSystemLibrary::SphereTraceMultiForObjects
//이곳에 디버깅이나. 편의기능을 좀 더 준 것이다. 

location, location : 위치 달라지면 거기 까지 이어가는 것

Untitled

1~ 잔뜩 뭔가 있다.

Untitled

프로젝트 셋팅 → 콜리전 에서 보면 이미 1~7번까지 정해져 있는 것이다. 지금 현재는 PhysicsBody를 사용 할 것

Untitled

Particle은 실제 System컴포넌트 , 이걸 가지고 반복플레이를 할 것이다. 한번 플레이가 됬다면, Reset을 해줘야한다.

//Particle Component ? 
	Particle->ResetParticles();
	Particle->SetActive(true);

만약

for (FHitResult hitResult : hitResults)
	{

	}

//이런식으로 하면, hitResult를 가져와서 계속 복사 생성한다. 그래서 강제로 레퍼런스를 붙인다. 
//hitResult값을 원본을 건드리는 것이 아니라. 가져다만 쓰는 거기 때문에, 

//실제 실무에서 이렇게 쓰인다. 
for (**const** FHitResult& hitResult : hitResults)
	{

	}

Impulse종류가 여러가지

설명

for (const FHitResult& hitResult : hitResults)
	{
		UStaticMeshComponent* mesh = Cast<UStaticMeshComponent> (hitResult.GetActor()->GetRootComponent());
		if (!!mesh && mesh->IsSimulatingPhysics())
			mesh->AddRadialImpulse(어디서 부터 나갈건지(우리위치), 얼마만큼 반격으로 날릴지, 힘이 얼마나 적용될지 질량 * ImpulseAmount,  );
		
	}

각각 다른

Untitled

RIF_Constant : 거리가 멀든 아니든 , 일정한 힘,

RIF_Linear : 선형으로 갈수록 힘이 줄어듬

실행 : Trigger 로 가게 되면 폭발하게 된다.

Untitled

만약 박스 모양을 더 작게 하면 멀리나갈까 작게 나갈까?

1000, mesh->GetMass() * ImpulseAmount 질량이 작으면 ImpulseAmount의 값이 작아진다. 그래서 원래는 절대질량을 뒤집어 줘야한다.

Untitled