UE5 Issues : C++ 충돌 처리

2025. 1. 27. 19:52·Unreal Engine

게임을 만들면서, 충돌 처리는 많이 사용하게 되는 로직 중 하나이다.

발판을 밟으면 일정 시간 이후 떨어지는 로직을 구현하면서 공부한 내용을 정리해 보았다.

 

1. NotifyActorBeginOverlap


  • 언리얼 레퍼런스
  • 두 액터가 겹쳐지기 시작할 때 발동되는 함수이다. (예를들어, 플레이어가 트리거로 걸어 들어가는 경우)
  • AActor 클래스를 상속받은 것들의 가상 함수로 제공되고, 아래와 같은 시그니처를 가진다.
virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
  • 이 함수를 사용하려면, 해당 액터와 다른 액터 모두 컴포넌트에 bGenerateOverlapEvents가 true로 설정되어야 한다.
  • Generate Overlap Events
      • BP의 디테일 창에서 검색하면 다음과 같은 값이 있는 것을 볼 수 있다.
    • 또한 C++ 코드에서도 다음과 같은 함수를 통해 설정해 줄 수 있다.
BoxCollision->SetGenerateOverlapEvents(true);

 

 

2. 사용 예제 및 Issues


먼저 문제가 생긴 이슈를 정리해 보자 

목적은 캐릭터가 액터를 밟으면, 그때 이후로 특정 시간 이후로 액터가 떨어지는 것을 구현하는 것이다.

  • 만든 액터는 static mesh하나를 가지고 있는 액터였다.
  • 이때 아래처럼 함수를 구현한 후 사용한다면, 우리가 원하는 결과를 얻지 못한다. (overlap 을 출력하지 않는다!)
void AFallingPlatform::NotifyActorBeginOverlap(AActor* OtherActor)
{
	Super::NotifyActorBeginOverlap(OtherActor);

	UE_LOG(LogTemp, Warning, TEXT("Overlap!"));

	//player 체크
	APlayerCharacter* PlayerCharacter = Cast<APlayerCharacter>(OtherActor);
	if (PlayerCharacter)
	{
		GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &AFallingPlatform::Falling, DelayTime, true);
	}
}
  • 그 이유는 해당 함수는 overlap 되었을 때 발동하는 함수이기 때문이다.
    • 우리가 가진 Static Mesh는 처음 만들게 되면 아래와 같은 콜리전 프리셋이 있다.
    • 아래와 같은 콜리전을 가지게 되면, 캐릭터는 해당 액터가 관통되지는 않지만, overlap 할 수는 없게 된다.
    • 그렇기 때문에 위의 코드에서 원하는동작이 이루어 지지 않고, overlap이라는 로그도 뜨지 않는다!

  • 그렇다면 다시 아래와 과 같이 콜리전을 수정하게 되면,

  • 아래 사진처럼 overlap되면서 로그도 뜨지만, 캐릭터가 액터에 겹쳐버리게 된다.

 

해결책

  • 해결책으로는 overlap을 하는 box collision을 추가로 만들어주면 된다.
  • 아래와 같이 액터의 생성자에서 Box Collision을 만들고, generate overlap event를 true로 켜주면 된다.
BoxCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("Box Collision"));
BoxCollision->SetupAttachment(RootComponent);

//box collision 크기 조절
BoxCollision->SetRelativeLocation(FVector(0.f, 0.f, 10.f));
BoxCollision->SetBoxExtent(FVector(50.f, 50.f, 30.f));
BoxCollision->SetGenerateOverlapEvents(true);
  • 우리가 원하는 동작을 하는 모습

 

 

3. OnComponentBeginOverlap


충돌을 처리할 때 NotifyActionBeginOverlap을 오버라이드 하는 방식이 아닌 다른 방식이 있다고 하여, 추가적으로 살펴보고, 코드를 작성해서 활용해 보았다.

  • 언리얼 레퍼런스
  • 무언가가(액터가 아니어도 괜찮음) 이 컴포넌트와 겹치기 시작할 때 호출되는 이벤트
  • 이벤트를 생성하려면, Generate Overlap Event가 활성화 되어있어야 한다. (Notify Actor Begin Overlap과 동일)
  • 그러나 이 이벤트는 컴포넌트 수준으로 동작하기 때문에 더 세밀한 조절이 가능하다.
    • 액터와 액터의 overlap보다 더 작은 수준의 overlap 체크
    • 또한 이 방식은 델리게이트를 통해 바인딩을 해서 사용하게 된다.

아직 사용법이 익숙하지 않아 아래와 같이 사용해 보았다. 

캐릭터가 액터 위에 올라가면(overlap되면) 액터가 올라가고, overlap이 끝나면 액터가 내려오는 것 구현

  • 헤더 파일
#pragma once

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

class UBoxComponent;

UCLASS()
class SCC_CH3_6_API AElevatePlatform : public AActor
{
	GENERATED_BODY()
	
public:	
	AElevatePlatform();

protected:
	virtual void BeginPlay() override;
	UFUNCTION()
	void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
	UFUNCTION()
	void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
public:	
	virtual void Tick(float DeltaTime) override;
	void Elevate(float DeltaTime);
	void Descened(float DeltaTime);

public:
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Platform|Components")
	UStaticMeshComponent* StaticMesh;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform|Components")
	UBoxComponent* BoxCollision;

private:
	float MoveSpeed;
	float MaxDistance;
	bool CanElevate;
	double StartPositionZ;
};
  • cpp 파일
#include "ElevatePlatform.h"
#include "Components/BoxComponent.h"
#include "PlayerCharacter.h"

AElevatePlatform::AElevatePlatform()
	:MoveSpeed(40.f)
	,MaxDistance(200.f)
	,CanElevate(false)
	,StartPositionZ(0.f)
{
	PrimaryActorTick.bCanEverTick = true;

	StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Static Mesh"));
	SetRootComponent(StaticMesh);

	static ConstructorHelpers::FObjectFinder<UStaticMesh>MeshAsset(TEXT("/Game/Fantastic_Village_Pack/meshes/props/deco/SM_PROP_firepit.SM_PROP_firepit"));
	if (MeshAsset.Succeeded())
	{
		StaticMesh->SetStaticMesh(MeshAsset.Object);
	}
	StaticMesh->SetRelativeScale3D(FVector(1.5f, 1.5f, 1.f));

	BoxCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("Box Collision"));
	BoxCollision->SetupAttachment(RootComponent);
	BoxCollision->SetGenerateOverlapEvents(true);

	BoxCollision->OnComponentBeginOverlap.AddDynamic(this, &AElevatePlatform::OnOverlapBegin);
	BoxCollision->OnComponentEndOverlap.AddDynamic(this, &AElevatePlatform::OnOverlapEnd);

}

void AElevatePlatform::BeginPlay()
{
	Super::BeginPlay();
	
	StartPositionZ = GetActorLocation().Z;
}

void AElevatePlatform::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	APlayerCharacter* PlayerCharacter = Cast<APlayerCharacter>(OtherActor);

	if (PlayerCharacter)
	{
		CanElevate = true;
	}
}

void AElevatePlatform::OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	APlayerCharacter* PlayerCharacter = Cast<APlayerCharacter>(OtherActor);

	if (PlayerCharacter)
	{
		CanElevate = false;
	}
}

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

	if (CanElevate)
	{
		Elevate(DeltaTime);
	}
	if (!CanElevate)
	{
		Descened(DeltaTime);
	}
}

void AElevatePlatform::Elevate(float DeltaTime)
{
	if (GetActorLocation().Z < MaxDistance)
	{
		AddActorLocalOffset(FVector(0.f, 0.f, MoveSpeed * DeltaTime));
	}
}

void AElevatePlatform::Descened(float DeltaTime)
{
	if(GetActorLocation().Z > StartPositionZ)	
	{
		AddActorLocalOffset(FVector(0.f, 0.f, -MoveSpeed * DeltaTime));
	}
}

 

구현된 결과 영상

 

'Unreal Engine' 카테고리의 다른 글

Unreal Engine - Simple Niagara (with cpp)  (0) 2025.02.04
Unreal Engine - Data Table  (0) 2025.02.03
UE5 Issues : Additive Animation (animation sequence 색깔)  (0) 2025.01.26
Unreal Engine - 캐릭터 만들기  (0) 2025.01.24
Unreal Engine - Enhanced Input System (PlayerController)  (2) 2025.01.22
'Unreal Engine' 카테고리의 다른 글
  • Unreal Engine - Simple Niagara (with cpp)
  • Unreal Engine - Data Table
  • UE5 Issues : Additive Animation (animation sequence 색깔)
  • Unreal Engine - 캐릭터 만들기
gbleem
gbleem
gbleem 님의 블로그 입니다.
  • gbleem
    gbleem 님의 블로그
    gbleem
  • 전체
    오늘
    어제
    • 분류 전체보기 (184)
      • Unreal Engine (73)
      • C++ (19)
      • 알고리즘(코딩테스트) (27)
      • TIL (60)
      • CS (4)
      • 툴 (1)
  • 블로그 메뉴

    • 홈
    • 카테고리
  • 링크

    • 과제용 깃허브
    • 깃허브
    • velog
  • 공지사항

  • 인기 글

  • 태그

    character animation
    C++
    Vector
    additive animation
    템플릿
    DP
    싱글턴
    BFS
    상속
    actor 클래스
    gamestate
    enhanced input system
    매크로 지정자
    blend pose
    const
    motion matching
    applydamage
    addonscreendebugmessage
    cin함수
    map을 vector로 복사
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gbleem
UE5 Issues : C++ 충돌 처리
상단으로

티스토리툴바