본문 바로가기

Unreal Engine 4/C++

<Unreal C++> 20 - Line Trace / Dynamic Delegate

필요한 개념


Channel : 채널로 검사
Profile : 프로파일 이름으로 검사(프로파일은 Engine->Collision->Preset에 있는 것 중에서 조사함)

ex)NoCollision, Pawn ....

Objects : 여러개의 오브젝트 타입을 검사

BP에서 LineTrace
LineTraceByChannel -> 한개 체크
LineTraceByProfile
LineTraceByObjects
MultiLineTraceByChannel -> 여러개 체크
MultiLineTraceByProfile
MultiLineTraceByObjects


C에서는(UKismetSystemLibrary::)
LineTraceSingle(얘는 Channel로 동작)
LineTraceSingleByProfile
LineTraceSingleForObjects
LineTraceMulti(얘는 Channel로 동작)
LineTraceMultiByProfile
LineTraceMultiForObjects



* Dynamic Delegate와 일반 Delegate와의 차이점
얘는 BP에서도 접근가능하다.(이 하나의 차이가 있음)
이 차이 때문의 정의 방식이 바뀜


// 일반 델리게이트트 파라미터 타입만 들어가는 반면
// 다이나믹 델리게이트는 파라미터 타입, 파라미터 명도 인자로 들어간다.
// 일치하지 않다면 콜되지 않음
// C에서는 알아서 자료형 및 이름 맞추고, BP에서는 알아서 맞춰주니깐..
// 1 : 자료형 명, 2 : 파라미터 타입, 3 : 파라미터명...
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FTraceResult, class AActor*, InActor, FLinearColor, InColor);

public:
// BlueprintAssignable : 블루프린트에서 이 이벤트를 사용가능하도록 명시(이거 해야 BP에서 사용가능)
UPROPERTY(BlueprintAssignable)
FTraceResult OnTraceResult;

하고 나면
BP_C02_LineTrace에서
OnTraceResult 바인딩, 언버안딩, 할당이 뜨게 된다.(카테고리는 이벤트디스패처)
바인딩 : 이벤트 연결
언바인딩 : 이벤트 해제
할당 : 이벤트 할당(이벤트 할당이 바인딩과 똑같음)

 

 

할당

 

바인딩

 

언바인딩 & 모든 이벤트 언바인딩

 


* 바인딩과 할당 차이(한번에 해주는게 할당)
바인딩 + AddCustomEvent 연결해주는게 -> 할당

if (UKismetSystemLibrary::LineTraceSingleByProfile(GetWorld(), start, end, "Pawn", false, ignoreActors, EDrawDebugTrace::ForOneFrame, hitResult, true, FLinearColor::Green, FLinearColor::Red))
{
if (OnTraceResult.IsBound())
{
FLinearColor color;
color.R = UKismetMathLibrary::RandomFloatInRange(0, 1);
color.G = UKismetMathLibrary::RandomFloatInRange(0, 1);
color.B = UKismetMathLibrary::RandomFloatInRange(0, 1);
color.A = 1.0f;

// 1 : 충돌한 놈, 2 : 바꿀색
OnTraceResult.Broadcast(hitResult.GetActor(), color);

}//if(LineTraceSingleByProfile)
}


BP에서 할당해주면 색이 랜덤으로 바뀌게 된다.

// 다이나믹 델리게이트는 일반 델리게이트와는 달리 AddDynamic()으로 연결
OnTraceResult.AddDynamic(this, &AC02_LineTrace::StartJump);

C02_LineTrance.h 내부 함수(StartJump)와 BP에 할당한 것이 같이 일어나서
점프도 되고 색도 바뀌게 된다.

 

 

 

* BP_C02_LineTrace

 


BP에 Retriggerable Delay
Delay는 최초 호출된 시간으로부터 해당 시간까지 지나면 몇번이 호출되도 해당 시간이 되면 호출 Retriggerable Delay는 계속 호출된 시간을 갱신해서 호출하므로
최종적으로 호출된 시간으로부터 해당 시간이 흐른 후 호출
(ex) 계속 들어오면 마지막으로 들어온 시간으로 부터 2초 뒤에)
그냥 Delay는 몇번이 콜 되었는 최초의 시점으로 부터
Retriggerable Delay는 콜된 마지막 시점으로 부터


주로 BP와 상호간의 할당이나 호출이 가능하도록 해야해서 대부분 Dynamic 델리게이트를 사용
컴포넌트 비긴 오버렙이나 액터 비긴 오버렙은 DynamicSparseDelegate를 사용
Sparse는 그걸 쓸 수 있는 자료형을 한정시킴(거의 언리얼 내부적으로만 Sparse를 사용할뿐 거의 Dynamic을 사용)

정리
DynamicDelegate
- BlueprintAssingable로 BP에서 할당이나 호출이 가능함
- AddDynamic으로 연결
- 그 외에는 일반 델리게이트와 동일

 

 

 

 

 

C01_Cylinder.h


더보기
#pragma once

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

UCLASS()
class UONLINE_03_CPP_API AC01_Cylinder : public AActor
{
	GENERATED_BODY()

private:
	UPROPERTY(VisibleDefaultsOnly)
		class USceneComponent* Scene;

	UPROPERTY(VisibleDefaultsOnly)
		class UTextRenderComponent* Text;

	UPROPERTY(VisibleDefaultsOnly)
		class UStaticMeshComponent* Mesh;
	
public:	
	AC01_Cylinder();

protected:
	virtual void BeginPlay() override;
};

 

 

 

 

 

 

 

C01_Cylinder.cpp


더보기
#include "C01_Cylinder.h"
#include "Global.h"
#include "Components/TextRenderComponent.h"
#include "Components/StaticMeshComponent.h"

AC01_Cylinder::AC01_Cylinder()
{
	CHelpers::CreateComponent<USceneComponent>(this, &Scene, "Scene");
	CHelpers::CreateComponent<UTextRenderComponent>(this, &Text, "Text", Scene);
	CHelpers::CreateComponent<UStaticMeshComponent>(this, &Mesh, "Mesh", Scene);

	Text->SetRelativeLocation(FVector(0, 0, 140));
	Text->SetRelativeRotation(FRotator(0, 180, 0));
	Text->SetRelativeScale3D(FVector(2));
	Text->TextRenderColor = FColor::Red;
	Text->HorizontalAlignment = EHorizTextAligment::EHTA_Center;
	Text->Text = FText::FromString(GetName());

	UStaticMesh* mesh;
	CHelpers::GetAsset<UStaticMesh>(&mesh, "StaticMesh'/Game/Meshes/M_Cylinder.M_Cylinder'");
	Mesh->SetStaticMesh(mesh);
	Mesh->SetRelativeScale3D(FVector(1, 1, 2.5f));
}

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

 

 

C02_LineTrace.h


더보기
#pragma once

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

// 일반 델리게이트트 파라미터 타입만 들어가는 반면
// 다이나믹 델리게이트는 파라미터 타입, 파라미터 명도 인자로 들어간다.
// 일치하지 않다면 콜되지 않음
// C에서는 알아서 자료형 및 이름 맞추고, BP에서는 알아서 맞춰주니깐..
// 1 : 자료형 명, 2 : 파라미터 타입, 3 : 파라미터명...
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FTraceResult, class AActor*, InActor, FLinearColor, InColor);

UCLASS()
class UONLINE_03_CPP_API AC02_LineTrace : public AActor
{
	GENERATED_BODY()

private:
	UPROPERTY(VisibleDefaultsOnly)
		class USceneComponent* Scene;

	UPROPERTY(VisibleDefaultsOnly)
		class UTextRenderComponent* Text;

public:	
	AC02_LineTrace();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

private:
	UFUNCTION()
		void StartJump(class AActor* InActor, FLinearColor InColor);
	
	// 블루프린트에서 콜 되도록
	UFUNCTION(BlueprintCallable)
		void RestoreColor(class ACPlayer* InPlayer);

private:
	TArray<class AC01_Cylinder*> Cylinders;

public:
	// BlueprintAssignable : 블루프린트에서 이 이벤트를 사용가능하도록 명시(이거 해야 BP에서 사용가능)
	UPROPERTY(BlueprintAssignable)
		FTraceResult OnTraceResult;

};

 

 

 

 

 

 

 

C02_LineTrace.cpp


더보기
#include "C02_LineTrace.h"
#include "Global.h"
#include "CPlayer.h"
#include "C01_Cylinder.h"
#include "Components/TextRenderComponent.h"

AC02_LineTrace::AC02_LineTrace()
{
	PrimaryActorTick.bCanEverTick = true;

	CHelpers::CreateComponent<USceneComponent>(this, &Scene, "Scene");
	CHelpers::CreateComponent<UTextRenderComponent>(this, &Text, "Text", Scene);

	Text->SetRelativeLocation(FVector(0, 0, 140));
	Text->SetRelativeRotation(FRotator(0, 180, 0));
	Text->SetRelativeScale3D(FVector(2));
	Text->TextRenderColor = FColor::Red;
	Text->HorizontalAlignment = EHorizTextAligment::EHTA_Center;
	Text->Text = FText::FromString(GetName());
}

void AC02_LineTrace::BeginPlay()
{
	Super::BeginPlay();

	// 배치되어있는 실린더 2개를 찾아옴
	CHelpers::FindActors<AC01_Cylinder>(GetWorld(), Cylinders);

	// 다이나믹 델리게이트는 일반 델리게이트와는 달리 AddDynamic()으로 연결
	OnTraceResult.AddDynamic(this, &AC02_LineTrace::StartJump);
}

void AC02_LineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	// 0번에서 1번까지 선을 그러봄
	FVector start = Cylinders[0]->GetActorLocation();
	FVector end = Cylinders[1]->GetActorLocation();

	//DrawDebugLine
	{
		start.Z -= 10;
		end.Z -= 10;

		DrawDebugLine(GetWorld(), start, end, FColor::Yellow, false);
	}

	// LineTrace는 매 프레임마다 해당 선에 겹치는 객체가 있는지
	// 체크해야 하므로 Tick에 정의함
	//LineTrace
	{
		start.Z += 10;
		end.Z += 10;

		TArray<AActor*> ignoreActors;
		// 실린더들 무시하도록
		ignoreActors.Add(Cylinders[0]);
		ignoreActors.Add(Cylinders[1]);

		FHitResult hitResult;
		// Pawn을 찾을 것이므로 Profile의 이름은 Pawn으로 입력
		// 5 : 삼각형 마다 충돌할거냐? 우리는 충돌체로만 할거라서
		// 6 : 충돌에서 제거할 액터를 넣어달라
		// 7 : 드로우모드 지정 (EDrawDebugTrace::ForOneFrame(매프레임마다 그려라))
		// 8 : HitResult(히트 되었을떄 결과 리턴받아라)
		// 9 : 자기자신을 제거할거냐
		// 10 : 선의 색상
		// 11 : 충돌했을때 색상
		// 12 : 몇초동안 그릴거냐?(틱에서는 의미없음)
		// 하나라도 충돌된게 있다면 true가 나옴
		if (UKismetSystemLibrary::LineTraceSingleByProfile(GetWorld(), start, end, "Pawn", false, ignoreActors, EDrawDebugTrace::ForOneFrame, hitResult, true, FLinearColor::Green, FLinearColor::Red))
		{
			if (OnTraceResult.IsBound())
			{
				FLinearColor color;
				color.R = UKismetMathLibrary::RandomFloatInRange(0, 1);
				color.G = UKismetMathLibrary::RandomFloatInRange(0, 1);
				color.B = UKismetMathLibrary::RandomFloatInRange(0, 1);
				color.A = 1.0f;

				// 1 : 충돌한 놈, 2 : 바꿀색
				OnTraceResult.Broadcast(hitResult.GetActor(), color);

			}//if(LineTraceSingleByProfile)
		}

	}

}

void AC02_LineTrace::StartJump(AActor* InActor, FLinearColor InColor)
{
	ACPlayer* player = Cast<ACPlayer>(InActor);
	CheckNull(player);

	player->Jump();
}

void AC02_LineTrace::RestoreColor(ACPlayer* InPlayer)
{
	InPlayer->ChangeColor(FLinearColor(1, 1, 1));
}

 

 

 

 

 

결과


 

 

'Unreal Engine 4 > C++' 카테고리의 다른 글

<Unreal C++> 24 - Gun Shooting Mode(Rifle Equip)  (0) 2022.04.24
<Unreal C++> 22 - SweepTrace  (0) 2022.04.24
<Unreal C++> 19 - Function Override  (0) 2022.04.15
<Unreal C++> 18 - Event  (0) 2022.04.15
<Unreal C++> 16 - Multicast Delegate  (0) 2022.04.15