프로그래밍 공부
작성일
2024. 5. 1. 15:44
작성자
WDmil
728x90

플레이어블 캐릭터 주변의 오버랩 엑터를 표시할 수 있다.

필요한 객체를 검출할 수 있다.


 InteractComponunt

 

충돌을 감지하는 컴포넌트를 생성한다. 해당 컴포넌트는 캐릭터의 주변에 생성되며, 지정된 오버렙된 액터들 중 지정된 엑터를 검출하고, 배열에 집어넣을 것이다.

 

배열에 들어간 객체를 검사해서 가장 짧은 DIstance를 가진 객체를 검출해낸다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/CapsuleComponent.h"
#include "InteractComponunt.generated.h"

/**
 * 1. 상호작용 가능한 물체 감지
 * 2. 물체 중에서도 최우선 순위 알고리즘으로 객체 골라내기
 * 3. 그걸 리턴하기.
 * 4. UI 띄우기
 */

class ABaseCharacter;

UCLASS()
class FTPSGAME_API UInteractComponunt : public UCapsuleComponent
{
	GENERATED_BODY()

	UPROPERTY()
	TObjectPtr<ABaseCharacter> OwnerCharacter;

	UPROPERTY()
	TArray<AActor*> InteractObjects;

public:
	UInteractComponunt();
	virtual void BeginPlay() override;
	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFuntion) override;

private:
	UFUNCTION()
	void AddInteractObject(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	void RemoveInteractObject(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "Components/InteractComponunt.h"
#include "Actors/BaseCharacter.h"
#include "Kismet/KismetMathLibrary.h"
#include "Interface/Interfaces.h"
#include "Utilities/Helper.h"


UInteractComponunt::UInteractComponunt()
{
	PrimaryComponentTick.bCanEverTick = true;

	{
		SetCollisionProfileName("InteractCollision");
	}
}

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

	OwnerCharacter = Cast<ABaseCharacter>(GetOwner());

	// size
	{
		const float Radius = OwnerCharacter->GetCapsuleComponent()->GetScaledCapsuleRadius() * 1.7f;
		const float Height = OwnerCharacter->GetCapsuleComponent()->GetScaledCapsuleHalfHeight() * 1.2f;
		
		SetCapsuleRadius(Radius);
		SetCapsuleHalfHeight(Height);
	}

	// Delegate
	OnComponentBeginOverlap.AddDynamic(this, &UInteractComponunt::AddInteractObject);
	OnComponentEndOverlap.AddDynamic(this, &UInteractComponunt::RemoveInteractObject);

}

void UInteractComponunt::AddInteractObject(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	InteractObjects.AddUnique(OtherActor);
}

void UInteractComponunt::RemoveInteractObject(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	InteractObjects.Remove(OtherActor);
}

void UInteractComponunt::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFuntion)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFuntion);
	
	for (auto* Actor : InteractObjects)
	{
		static float Min = FLT_MAX;
		const FVector Point = Actor->GetActorLocation();
		const FVector LineOrigin = OwnerCharacter->GetControllLocation();
		const FVector LineDirection = OwnerCharacter->GetControlRotation().Vector();
		float Distance = UKismetMathLibrary::GetPointDistanceToLine(Point, LineOrigin, LineDirection);
		
		Min = UKismetMathLibrary::Min(Min, Distance);
		Helper::Print(Point);
	}

	
}

 

overlap이벤트로 생성된 객체들을 InteractObjects 배열에 집어넣고, 해당 배열을 늘 순환하며, 순환중 가장 짧은 DIstance를 가진 객체를 표시할 것 이다.

 

MinDIstance의 측정방식은, 현재 지정된 점에서 뻗어나간 반직선에 가장 짧은 거리를 가진 엑터가 된다.

 

Collision의 객체 재한을 InteractCollision 로 정해두고, 데이터를 처리하여, 불필요한 엑터의 오버랩 처리를 최대한 피한다.


테스트

728x90