2025 05 24 -2025 05 25

2025. 5. 26. 02:12WIL

2025 05 24 -  캐릭터 애니메이션 문제 해결 ,  캐릭터 cross hair 줌과 발사 

이전에 캐릭터가 뛰는 모션을 취할때 blendspace를 통해 방향과 바라보는 방향에 따라 YawAxis를 구하여 각각 다른 모션을 취하도록 설정을 했지만 원하는 모션이 아닌 하나의 고정된 모션만 나오는 문제를 해결하였다 .

원인은 blendspace는 x축과 y축의 Setting이 존재하는데 나는 speed는 향후에 조건으로 하고 우선 방향만 조건으로 만들어 넣어서 y축 값은 0으로 고정이 되어서 그런 이상이 생겼었다 그래서 향후에 y축값을 입력받기로 하고 수정을 하였다 

이로써 원하는 동작이 되었다 

그리고 기존에 crosshair에서 총을 발사하면 crosshair에 퍼짐 현상을 추가하고싶어서

void AShooterCharacter::CalculateCrosshairSpread(float DeltaTime)
{

	FVector2D WalkSpeedRange{ 0.f, 600.f };
	FVector2D VelocityMultiplierRange{ 0.f,1.f };
	FVector Velocity{ GetVelocity() };
	Velocity.Z = 0;
	// MOVE
	CrosshairVelocityFactor = FMath::GetMappedRangeValueClamped(WalkSpeedRange, VelocityMultiplierRange,Velocity.Size());
	// JUMP 
	if (GetCharacterMovement()->IsFalling())
	{
		//Spread crosshairs slowly while in air
		CrosshairInAirFactor = FMath::FInterpTo(
			CrosshairInAirFactor,
			2.25f,
			DeltaTime,
			2.25f);
	}
	else
	{
		CrosshairInAirFactor = FMath::FInterpTo(
			CrosshairInAirFactor,
			0.f,
			DeltaTime,
			30.f);
	}
	//AMING
	if (bAiming)
	{
		CrosshairAimFactor = FMath::FInterpTo(
			CrosshairAimFactor,
			0.5f,
			DeltaTime,
			2.25f);
		
	}
	else
	{
		CrosshairAimFactor = FMath::FInterpTo(
			CrosshairAimFactor,
			0.f,
			DeltaTime,
			30.f);
	}
	// 0.05초 후에 발사 
	if (bFiringBullet)
	{
		CrosshairShootingFactor = FMath::FInterpTo(
			CrosshairShootingFactor, 
			0.3f, 
			DeltaTime, 
			60.f);
	}
	else
	{
		CrosshairShootingFactor = FMath::FInterpTo(
			CrosshairShootingFactor,
			0.f,
			DeltaTime,
			60.f);
	}
	CrosshairSpreadMultiplier = 0.5f + CrosshairVelocityFactor + CrosshairInAirFactor - CrosshairAimFactor + CrosshairShootingFactor;
}

해당 함수에는 crosshair가 퍼지는 정도를 계산하는 식으로 해당 crosshairSpreadMultiplier는 movement 나 총을 발사 중일 경우에 따라 퍼짐을 추가해 준다 

현재 25일차에 진행하고있는 무기에 collision Check 수정을 못해서 무기에서 hitparticle이 나오는데 향후 수정하겠다

void AShooterCharacter::ChangeCameraView(float DeltaTime)
{
	if (bAiming)
	{
		CameraCurrentFOV = FMath::FInterpTo(CameraCurrentFOV, CameraZoomFOV, DeltaTime, ZoomInterpSpeed);
	}
	else
	{
		CameraCurrentFOV = FMath::FInterpTo(CameraCurrentFOV, CameraDefaultFOV, DeltaTime, ZoomInterpSpeed);
	}
	GetFollowCamera()->SetFieldOfView(CameraCurrentFOV);
}

줌같은 경우에는 우클릭으로 inputaction을 만들고 trigger때 baiming이 true가 되어 카메라의 fieldofview의 크기를 줄이고 다시 completed가 되면 원상복귀한다. 또한 줌을 할때는 crosshair spread는 줄어들도록 설정을 하였다 

2025 05 25 - 캐릭터 무기 관련 클래스 제작 

현재 무기에 관한 클래스를 제작 전 부모 클래스 격인 item class 를 만들었다

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

#pragma once

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


UENUM(BlueprintType)
enum class EItemRarity : uint8
{
	EIR_Damaged UMETA(DisplayName = "Damaged"),
	EIR_Common UMETA(DisplayName = "Common"),
	EIR_UnCommon UMETA(DisplayName = "UnCommon"),
	EIR_Rare UMETA(DisplayName = "Rare"),
	EIR_Legendary UMETA(DisplayName = "Legendary"),
	EIR_Max UMETA(DisplayName = "DefaultMax"),

};

UCLASS()
class SHOOTERGAME_API AItem : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AItem();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;



	UFUNCTION()
	void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent,
		AActor* OtherActor,
		UPrimitiveComponent* OtherComp, 
		int32 OtherBodyIndex,
		bool bFromSweep,
		const FHitResult& Hitresult
	);

	UFUNCTION()
	void OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent,
		AActor* OtherActor,
		UPrimitiveComponent* OtherComp,
		int32 OtherBodyIndex);

	//별 ui 활성화
	void SetActiveStars();

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

private:

	// 아이템 mesh
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	TObjectPtr<USkeletalMeshComponent> ItemMesh;
		

	// 라인트레이스를 보여주기위해 
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UBoxComponent> CollisionBox;

	// 아이템 정보 popup
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UWidgetComponent> PickupWidget;
	// 아이템 트레싱 범위 
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class USphereComponent> AreaSphere;

	// 아이템 name 
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	FString ItemName;

	//아이템 count
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	int32 ItemCount;

	UPROPERTY(EditAnywhere , BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	EItemRarity ItemRarity;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = "true"))
	TArray<bool> ActiveStars;

public:
	FORCEINLINE UWidgetComponent* GetPickupWidget() const { return PickupWidget; };
};

 

변수로 아이템의 이름, 아이템 수 , 아이템의 희귀도 (enum)이 구성 요소이고 아이템에 관한 정보를 보여주는 widgetbp를 가지고있다.

void AItem::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& Hitresult)
{
	if (OtherActor)
	{
		AShooterCharacter* ShooterCharacter = Cast<AShooterCharacter>(OtherActor);
		if (ShooterCharacter)
		{
			ShooterCharacter->IncreamentOverlapppedItemCount(1); // 만약 캐릭터와 겹치면 OVERLAP COUNT 증가 
			
		}

	}
}

void AItem::OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (OtherActor)
	{
		AShooterCharacter* ShooterCharacter = Cast<AShooterCharacter>(OtherActor);
		if (ShooterCharacter)
		{
			ShooterCharacter->IncreamentOverlapppedItemCount(-1); // 만약 캐릭터와 겹치면 OVERLAP COUNT 감소 
		}

	}
}

주요 기능 함수로서 이건 아이템이 캐릭터와 overlap되면 캐릭터에게 오버랩된 아이템이 있는 정보를 주는 함수를 실행시켜 정보를 준다 

만약 캐릭터가 해당 아이템과 오버랩이 되고 바라본다면 해당 widget이 나오게 된다

void AShooterCharacter::TraceForItems()
{
	if (bShouldTraceItems)
	{
		FHitResult ItemTraceResult;
		FVector HitLocation;
		TraceUnderCrosshairs(ItemTraceResult, HitLocation);
		if (ItemTraceResult.bBlockingHit)
		{
			AItem* HitItem = Cast<AItem>(ItemTraceResult.GetActor());
			if (HitItem)
			{

				if (HitItem->GetPickupWidget())
				{

					HitItem->GetPickupWidget()->SetVisibility(true);
				}

				if (TraceHitItemLastFrame)
				{
					if (HitItem != TraceHitItemLastFrame)
					{
						//만약 마지막 프레임 아이템이랑 trace아이템 다르면 마지막프레임에 저장된 아이템 끄자 
						TraceHitItemLastFrame->GetPickupWidget()->SetVisibility(false);
					}
				}
				//마지막 프레임 아이템 트레이스 저장 
				TraceHitItemLastFrame = HitItem;
			}
			else if (TraceHitItemLastFrame) 
			{
				TraceHitItemLastFrame->GetPickupWidget()->SetVisibility(false);
			}

		}	
	}
	else if (TraceHitItemLastFrame) // 만약 트레이스가 된게 없어도 지우자 
	{
		TraceHitItemLastFrame->GetPickupWidget()->SetVisibility(false);
	}
}

이것으로 TraceUnderCrossHair이라는 전에 올렸던 tracechannel을 감지하는 방법을 이용하여 현재 crosshair에 아이템이 있다면 widget을 보여주고 아니면 안보여준다