Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- EnhancedInput
- Ajax
- 디자드
- flask
- Enhanced Input System
- 스마일게이트
- 프린세스메이커
- 언리얼뮤지컬
- JWT
- 으
- Express
- VUE
- 마인크래프트뮤지컬
- R
- Jinja2
- 레베카
- 스터디
- 데이터베이스
- 알고풀자
- 게임개발
- 카렌
- Unseen
- 프메
- node
- 언리얼프로그래머
- 미니프로젝트
- 파이썬서버
- 언리얼
- Bootstrap4
- 정글사관학교
Archives
- Today
- Total
Today, I will
[Unreal] 라인트레이스 C++ 본문
언리얼에서 라인트레이스 기능을 C++로 작성해보도록 한다.
캐릭터가 라인트레이스로 찾을 액터를 하나 C++로 만들어주고, 블루프린트를 만들어준다.
.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TraceTestActor.generated.h"
UCLASS()
class LECTURE_API ATraceTestActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATraceTestActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(VisibleAnywhere, Category = "MySettings")
class UBoxComponent* boxComp;
UPROPERTY(VisibleAnywhere, Category = "MySettings")
class UStaticMeshComponent* meshComp;
};
.ccp
#include "TraceTestActor.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
// Sets default values
ATraceTestActor::ATraceTestActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
boxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComponent"));
RootComponent = boxComp;
boxComp->SetBoxExtent(FVector(50));
boxComp->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
boxComp->SetCollisionObjectType(ECC_WorldDynamic);
meshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
meshComp->SetupAttachment(RootComponent);
boxComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
// Called when the game starts or when spawned
void ATraceTestActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ATraceTestActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
트레이스 채널을 하나 추가해준다.
DefaultEngine.ini에서 방금 추가한 채널명을 검색하여 확인해준다.(플레이어 코드에서 필요)
블루프린트 메쉬를 적당히 지정해주고
collisin 설정이 Block인지 필히 확인해준다.
이제 캐릭터에서 라인트레이스할 함수를 만들어준다.
.h
protected:
// APawn interface
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
// To add mapping context
virtual void BeginPlay();
virtual void Tick(float DeltaSeconds);
public:
/** Returns CameraBoom subobject **/
FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
/** Returns FollowCamera subobject **/
FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
// 1. 캐릭터의 피벗을 기준으로 정면 방향 15미터 이내에 있는 ATraceActor 액터 중에 가장 가까운 액터를 액터의 이름을 출력하는 함수를 선언하고, Tick에서 호출하고 싶다.
void SensorForNearestsActor();
// 2. 캐릭터의 피벗을 기준으로 전방 15미터 이내의 ATraceActor 액터 전부를 출력하는 함수를 선언하고, Tick에서 호출하고 싶다.
void SensorForAllActor();
.cpp
코드 스타일1이 주석처리되어 있고,, 코드스타일2가 작성되어 있는데
둘 다 정상 작동하는 코드이다.
#include "TraceTestActor.h"
void ALectureCharacter::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
SensorForAllActor();
}
void ALectureCharacter::SensorForNearestsActor()
{
/* 코드스타일1
FHitResult hit;
FVector pos = GetActorLocation();
FVector StandardVec = (FRotationMatrix(GetActorRotation()).GetUnitAxis(EAxis::X) * 1500.0f) + pos;
FCollisionQueryParams traceParam;
traceParam.AddIgnoredActor(this);
if (GetWorld()->LineTraceSingleByChannel(hit, pos, StandardVec, ECC_GameTraceChannel1, traceParam)) {
UE_LOG(LogTemp, Warning, TEXT("%s"), *hit.GetActor()->GetActorNameOrLabel());
DrawDebugLine(GetWorld(), pos, hit.ImpactPoint, FColor::Green, false, 0, 0, 2.0f);
DrawDebugBox(GetWorld(), hit.ImpactPoint, FVector(5.0f), FColor::Green, false, 0, 0, 1.5f);
}
else {
DrawDebugLine(GetWorld(), pos, StandardVec, FColor::Green, false, 0, 0, 2.0f);
}
*/
// 1. 캐릭터의 피벗을 기준으로 정면 방향 15미터 이내에 있는 ATraceActor 액터 중에 가장 가까운 액터를 액터의 이름을 출력하고 싶다.
// 코드스타일2
FHitResult* hit = new FHitResult;
FVector pos = GetActorLocation();
FVector frontVec = GetActorForwardVector();
FVector StandardVec = (frontVec * 150.0f) + pos;
FCollisionQueryParams* traceParam = new FCollisionQueryParams;
//DrawDebugLine(GetWorld(), pos, StandardVec, FColor::Green, false, 2.0f);
if (GetWorld()->LineTraceSingleByChannel(*hit, pos, StandardVec, ECC_GameTraceChannel1, *traceParam)) {
DrawDebugLine(GetWorld(), pos, StandardVec, FColor::Green, false, 2.0f);
AActor* a = hit->GetActor();
ATraceTestActor* TraceTestActor = Cast<ATraceTestActor>(a);
if (TraceTestActor) {
UE_LOG(LogTemp, Warning, TEXT("%s"), *TraceTestActor->GetActorNameOrLabel());
}
}
//참조자로 받는데 const로 받지 않는다는건 십중팔구 값을 채워주겠다는 뜻
}
void ALectureCharacter::SensorForAllActor()
{
// 2. 캐릭터의 피벗을 기준으로 전방 15미터 이내의 ATraceActor 액터 전부를 출력하고 싶다.
//LineTraceMultiByChannel
TArray<FHitResult> hits;
FVector pos = GetActorLocation();
FVector StandardVec = (FRotationMatrix(GetActorRotation()).GetUnitAxis(EAxis::X) * 1500.0f) + pos;
FCollisionQueryParams traceParam;
traceParam.AddIgnoredActor(this);
if (GetWorld()->LineTraceMultiByChannel(hits, pos, StandardVec, ECC_GameTraceChannel1, traceParam)) {
FVector newStartVec = pos;
for (const FHitResult& hit : hits) {
UE_LOG(LogTemp, Warning, TEXT("Mmulti test: %s"), *hit.GetActor()->GetActorNameOrLabel());
DrawDebugLine(GetWorld(), newStartVec, hit.ImpactPoint, FColor::Green, false, 0, 0, 1.5f);
newStartVec = hit.ImpactPoint;
DrawDebugBox(GetWorld(), hit.ImpactPoint, FVector(5.0f), FColor::Green, false, 0, 0, 1.5f);
}
}
else {
DrawDebugLine(GetWorld(), pos, StandardVec, FColor::Red, false, 0, 0, 1.5f);
}
}
멀티라인트레이스에서 Sweep로 Line과 비슷하다.
월드 상에 액터를 아래와 같이 배치하였을 때
라인트레이스 return 지점은 collision Block check여야 한다는 점을 유념해야 한다.
즉, mult 라인 트레이스를 쏘기 위해서는 마지막 액터만 block이고 앞의 두 액터는 overlap
멀티 라인트레이스 캡처 예시
사실 여러개를 식별하는 것은 라인트레이스 보다 오버랩이 용이하다.(라인멀티나 스윕멀티는 많이 쓰지 않음)
// 범위 안에 있는 block, overlap을 전부 체크(다만 block이 있어야 함)
void ALectureCharacter::SensorUsingOverlap()
{
// 영역의 안 밖을 체크함
TArray<FOverlapResult> hitResults;
FVector centerLoc = GetActorLocation();
// 쿼터니언과 로테이션은 서로 변환 가능
//FQuat playerRot = GetActorRotation().Quaternion();
//GetActorQuat().Rotator();
FQuat playerRot = GetActorQuat();
FCollisionQueryParams traceParam;
traceParam.AddIgnoredActor(this);
// 반지름 범위 안에 오버랩되는 것 중 채널 안의 애들 감지
if (GetWorld()->OverlapMultiByChannel(hitResults, centerLoc, playerRot, ECC_GameTraceChannel1, FCollisionShape::MakeSphere(1500), traceParam)) {
for (const FOverlapResult hitresult : hitResults) {
UE_LOG(LogTemp, Warning, TEXT("Overlap Test: %s"), *hitresult.GetActor()->GetActorNameOrLabel());
DrawDebugSphere(GetWorld(), hitresult.GetActor()->GetActorLocation(), 50, 10, FColor::Green, false, 0, 0, 1.5f);
}
}
DrawDebugSphere(GetWorld(), GetActorLocation(), 500, 10, FColor::Green, false, 0, 0, 1.5f);
}
'Unreal' 카테고리의 다른 글
[Unreal] virtual production tutorial 요약 (0) | 2024.03.06 |
---|---|
[Unreal, Virtual Production] VP 학습 계획 (2) | 2024.03.06 |
[언리얼 Metarial] fresnel reflectioin 이용하여 반투명 재질 만들기 (1) | 2024.01.25 |
[언리얼 그래픽스] Wet Ground, 노멀맵 믹싱 (0) | 2024.01.24 |
[Unreal Project] 싱글톤 패턴을 이용한 네트워크 플레이어 프로그래밍 (0) | 2024.01.13 |