LineTrace : Trace개요

C02_Cylinder클래스 생성

서로 사이에 선을 쏠 것 (Cylinder.cpp에서 경로따와서 만들어준 클래스 임)

Untitled

C02_Cylinder.h

#pragma once

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

UCLASS()
class U2110_03_API AC02_Cylinder : public AActor
{
	GENERATED_BODY()
	
private:
	UPROPERTY(VisibleDefaultsOnly)
		class USceneComponent* Root;

	UPROPERTY(VisibleDefaultsOnly)
		class UStaticMeshComponent* Mesh;

	UPROPERTY(VisibleDefaultsOnly)
		class UTextRenderComponent* Text;

public:	
	AC02_Cylinder();

protected:
	virtual void BeginPlay() override;
};

C02_Cylinder.cpp

#include "C02_Cylinder.h"
#include "Global.h"
#include "Components/StaticMeshComponent.h"
#include "Components/TextRenderComponent.h"

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

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

	Text->SetRelativeLocation(FVector(0, 0, 150));
	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 AC02_Cylinder::BeginPlay()
{
	Super::BeginPlay();
	
}

선 쏠 것 만들어준다.

C02_LineTrace클래스 생성

C02_LineTrace.h

#pragma once

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

//델리게이트 정의 
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FLineTraceResult, class AActor*, InActor, FLinearColor, InColor);

UCLASS()
class U2110_03_API AC02_LineTrace : public AActor
{
	GENERATED_BODY()
	
private:
	UPROPERTY(EditAnywhere)
		FVector LaunchAmount = FVector(0, 0, 200); //방향 위쪽 수직으로

private:
	UPROPERTY(VisibleDefaultsOnly)
		class USceneComponent* Root;

	UPROPERTY(VisibleDefaultsOnly)
		class UTextRenderComponent* Text;

public:	
	AC02_LineTrace();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

private:
	UFUNCTION()
		void StartLaunch(class AActor* InActor, FLinearColor InColor); //자료형 뒤에 콤마 제거

public:
	UPROPERTY(BlueprintAssignable)
		FLineTraceResult OnLineTraceResult;

private:
//배열로 불러오기 
	TArray<class AC02_Cylinder *> Cylinders;
};

델리게이트

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FLineTraceResult, class AActor*, InActor, FLinearColor, InColor);

다이나믹 델리게이트(Dynamic Deligate) : 일반적인 델리게이트와 다 동일 하지만. 이것은 블루프린트에 공개가 될 수 있는 델리게이트 이다. (블루프린트 이벤트 디스패쳐가 다이나믹 델리게이트)

특징 : 기존 파라미터에 타입하고 갯수만 일치 시켰었는데. 다이나믹 델리게이트는 변수명 까지 일치 시켜야 한다. (블루프린트에 변수명으로 공개가 되기 때문)

싱글/멀티 다 똑같다.

매크로 생성 : 다이나믹 델리게이트 | Arguments(논거) Type(타입명) / ArgumentName(파라미터 명)

Untitled

Public 내부적으로 정의

public:
	UPROPERTY(BlueprintAssignable)
		FLineTraceResult OnLineTraceResult;

이것은 지금 변수인데. 변수는 UProPerty 가 붙어야한다. BlueprintAssignable : 블루프린트 이벤트로 간주

C02_LineTrace.cpp

#include "C02_LineTrace.h"
#include "Global.h"
#include "C02_Cylinder.h"
#include "GameFramework/Character.h" //캐릭터 불러오기
#include "Components/TextRenderComponent.h"

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

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

	Text->SetRelativeLocation(FVector(0, 0, 20));
	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 AC02_LineTrace::BeginPlay()
{
	Super::BeginPlay();
	
//여려개를 찾아올 것 
	CHelpers::FindActors<AC02_Cylinder>(GetWorld(), Cylinders);
	OnLineTraceResult.A**ddDynamic(this, &AC02_LineTrace::StartLaunch);
}**

void AC02_LineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	CheckFalse(Cylinders.Num() == 2); // 길이?

	FVector start = Cylinders[0]->GetActorLocation();
	FVector end = Cylinders[1]->GetActorLocation();

	//DrawDebugLine(영역구분 블럭)
	{
		start.Z -= 20; //GetActorLocation이 중앙점으로 리턴되서 낮춤
		end.Z -= 20;

		DrawDebugLine(GetWorld(), start, end, FColor::Blue); //매프레임 마다. 그리기
	}

	//LineTrace
	{
		start.Z += 40;
		end.Z += 40;

		TArray<AActor*> ignores;
//제거 할 것 
		ignores.Add(Cylinders[0]);
		ignores.Add(Cylinders[1]);

		FHitResult hitResult;
		UKismetSystemLibrary::LineTraceSingleByProfile(GetWorld(), start, end, "Pawn", false, ignores, EDrawDebugTrace::ForOneFrame, hitResult, true);
		//"Pawn" 은 폰타입 이지만 Profile은 Pawn에 있는 설정으로 추적을 하겠다는 
		if (hitResult.bBlockingHit)
		{
			if (OnLineTraceResult.IsBound()) //연결 되어 있는 것들 콜 
				OnLineTraceResult.Broadcast(hitResult.GetActor(), FLinearColor::MakeRandomColor()); 
		}
	}
}

void AC02_LineTrace::StartLaunch(AActor* InActor, FLinearColor InColor)
{
	ACharacter* character = Cast<ACharacter>(InActor); //형변환 InActor가 Null이거나 Casting 실패면. Null로 리턴된다.
	if (!!character) //Null 체크 
		character->LaunchCharacter(LaunchAmount, true, false); //밀려 나가는 런치
}

F9 누르고 디버그 모드에서 F5 누르면 에디터 창 하나가 뜨는데. 이 해당 창에서는 뭘 편집하면 안된다. (플레이 해보면 걸린다. 마우스 갖다대면 무엇이 문제 인지 찾을 수 있다.)

CHelpers에 중요한 것

문제 참고

CHelpers.h 이곳에서 빠진 것

template<typename T>
	static void FindActors(UWorld* World, TArray<T *> OutArray)
	{
		OutArray.Empty(); //배열

		for (AActor* actor : World->GetCurrentLevel()->Actors)
		{
			if (!!actor && actor->IsA<T>())
				OutArray.Add(Cast<T>(actor)); 
		}
	}

지금 이곳에서 배열에 넣어서 리턴해줄려고 되어있는 것이다. 이렇게 그냥 두면 지역 변수가 되어버린다. / 지역변수면 이안에서 끝나고서 소멸 되어 버리는 것이다. (즉 호출 한데랑 연관이 없어지는 변수가 되어버린다)

template<typename T>
	static void FindActors(UWorld* World, TArray<T *>& OutArray) //참조로 바꿔줘야한다. 
	{
		OutArray.Empty(); //배열

		for (AActor* actor : World->GetCurrentLevel()->Actors)
		{
			if (!!actor && actor->IsA<T>())
				OutArray.Add(Cast<T>(actor)); 
		}
	}

Untitled

BP_C02_LineTrace

Change color 색상 변경 이벤트 디스패쳐 같은

Untitled

실행

배치

Untitled

플레이 하면 선이 생긴다

Untitled

가까이 다가가면 런치를 주었기 때문에. 위로 띄어진다.

Untitled

뛰면서 색상도 바뀌는 것을 확인 할 수 있다.

MultiLineTrace

셋팅

Untitled

Trace 에서 보면 겹치는 것을 반환해준다.

Untitled

C03_MultiLineTrace 클래스 생성

C03_MultiLineTrace.h

#pragma once

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

UCLASS()
class U2110_03_API AC03_MultiLineTrace : public AActor
{
	GENERATED_BODY()
	
private:
	UPROPERTY(VisibleDefaultsOnly)
		class USceneComponent* Root;

	UPROPERTY(VisibleDefaultsOnly)
		class UTextRenderComponent* Text;

public:	
	AC03_MultiLineTrace();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

private:
	float TotalTime = 0;
};

C03_MultiLineTrace.cpp

#include "C03_MultiLineTrace.h"
#include "Global.h"
#include "Components/TextRenderComponent.h"

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

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

	Text->SetRelativeLocation(FVector(0, 0, 20));
	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 AC03_MultiLineTrace::BeginPlay()
{
	Super::BeginPlay();
	
}

void AC03_MultiLineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

//쏠 방향 
	FVector start = GetActorLocation();
//시작지점 서로 간격 
	FVector start1 = FVector(start.X + 50, start.Y, start.Z);
	FVector start2 = FVector(start.X - 50, start.Y, start.Z);

//End 지점
	FVector end1 = start1 * GetActorForwardVector() * 500; 
	FVector end2 = start2 * GetActorForwardVector() * 500;

	
	TArray<AActor*> ignores;
	TArray<FHitResult> hitResult1;
	TArray<FHitResult> hitResult2;

//check를 Object 타입으로
	TArray<TEnumAsByte<EObjectTypeQuery>> queries;
	queries.Add(EObjectTypeQuery::ObjectTypeQuery1);

//channel하고 Object가 다른데 Multi가 channel이다. 
	UKismetSystemLibrary::LineTraceMulti(GetWorld(), start1, end1, ETraceTypeQuery::TraceTypeQuery1, false, ignores, EDrawDebugTrace::ForOneFrame, hitResult1, true);
	UKismetSystemLibrary::LineTraceMultiForObjects(GetWorld(), start2, end2, queries, false, ignores, EDrawDebugTrace::ForOneFrame, hitResult2, true);

//충돌했을 때 결과 확인 	
	TotalTime += DeltaTime; // 델타 타임 더해줘야 2초마다 가능 
	if (TotalTime >= 2.0f) //2초마다 출력
	{
		TotalTime = 0;
		
		CLog::Log("Channel");
		for (FHitResult& hitResult : hitResult1)//hit 결과 
			CLog::Log(hitResult.GetActor()->GetName());

		CLog::Log("Objects");
		for (FHitResult& hitResult : hitResult2)
			CLog::Log(hitResult.GetActor()->GetName());
	}
		
}

TraceTypeQuery1 : 콜리전에서 1번이 VIsibility. 2번이 camera 3번부터는 정의해서 사용

Untitled

LineTraceMultiForObjects : LineTraceMultiByObjectType을 콜한다.

Untitled

블프 만들어서 실행

Untitled

출력로그 결과

Untitled

지금 첫번째 꺼는 통과 안되고 두번째 것만 통과 되서 출력되는 것을 볼 수 있다.

이게 그런데 차이가 있다. 앞에 있는 벽의 콜리전을 Custom → 겹칩으로 바꿔 준다

Untitled

그러면 하나를 뚫는다. 이게 Overlap을 뚫고 그다음 것으로 간다. 즉 Overlap이 첫번째 block 까지 overlap이 같이 켜지고 첫번째에서 끝난다.

Untitled

그래서 결과를 보면

Untitled

채널 하고 Overlap이 다 나왔다.

GP: Display: Channel
GP: Display: Cube23
GP: Display: Cube22

그런데 두번 째 것은 overlap이고 뭐고 다 뚫고 지나갔다.

GP: Display: Objects
GP: Display: Cube23
GP: Display: Cube22
GP: Display: Cube18_2
GP: Display: Simple_Wall_2x23
GP: Display: Simple_Wall_2x34

channel은 유리창 같은 곳을 관통해서 폭파나 그런걸 일으킬 때 사용하고.

사운드는 UGamePlayStatics에 PlaySound 똑같이 다 있다.

블프에 sound 있는데.

Untitled

갖다 대면. 해당 경로에 있는거 가져와서 사용하면 된다.

Untitled