LineTrace : Trace개요
C02_Cylinder클래스 생성
서로 사이에 선을 쏠 것 (Cylinder.cpp에서 경로따와서 만들어준 클래스 임)
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(파라미터 명)
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));
}
}
BP_C02_LineTrace
Change color 색상 변경 이벤트 디스패쳐 같은
실행
배치
플레이 하면 선이 생긴다
가까이 다가가면 런치를 주었기 때문에. 위로 띄어진다.
뛰면서 색상도 바뀌는 것을 확인 할 수 있다.
MultiLineTrace
셋팅
Trace 에서 보면 겹치는 것을 반환해준다.
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번부터는 정의해서 사용
LineTraceMultiForObjects : LineTraceMultiByObjectType을 콜한다.
블프 만들어서 실행
출력로그 결과
지금 첫번째 꺼는 통과 안되고 두번째 것만 통과 되서 출력되는 것을 볼 수 있다.
이게 그런데 차이가 있다. 앞에 있는 벽의 콜리전을 Custom → 겹칩으로 바꿔 준다
그러면 하나를 뚫는다. 이게 Overlap을 뚫고 그다음 것으로 간다. 즉 Overlap이 첫번째 block 까지 overlap이 같이 켜지고 첫번째에서 끝난다.
그래서 결과를 보면
채널 하고 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 있는데.
갖다 대면. 해당 경로에 있는거 가져와서 사용하면 된다.