Infinite Fighter 개발일지 (10)

유영준·2023년 5월 22일
0

UE5 UNSEEN

목록 보기
10/18
post-thumbnail

2023.05.15 ~ 2023.05.21 개발일지

추가한 부분

파티클 추가

무기와 캐릭터에게 소캣을 달아주고, 그 소켓을 통해 Trail 파티클을 추가하는 방식을 통해 파티클을 추가해보았다

먼저 무기에 Top과 Bottom 이라는 소켓을 추가해주었다

추가한 소켓과, 파티클을 코드를 통해 불러와보았다

IFAxe.cpp

AIFAxe::AIFAxe()
{
	...
    
	// setting TrailParticle
	TrailParticleComponent = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("TRAIL_PARTICLE_COMPONENT"));
	TrailParticleComponent->SetupAttachment(Axe);

	static ConstructorHelpers::FObjectFinder<UParticleSystem>TRAIL_PARTICLE
	(TEXT("/Game/InFiniteFighter/FX/Leviathon/P_AxeWeaponTrail.P_AxeWeaponTrail"));
	if (TRAIL_PARTICLE.Succeeded())
		TrailParticleComponent->SetTemplate(TRAIL_PARTICLE.Object);

	...

}

...

void AIFAxe::Throw()
{
	...
    
	TrailParticleComponent->BeginTrails(TEXT("Top"), TEXT("Bottom"), ETrailWidthMode_FromCentre, 1.0f);
}

이를 통해 도끼를 던질때와 돌아올때 파티클이 나가도록 구현을 하였다


애니메이션 내부에 Trail 파티클 추가하기

동일한 Trail 파티클을 애니메이션 내부에 삽입하는 방식으로 구현을 해보았다

노티파이 State를 통해 파티클을 추가하고, 지정된 파티클과 시작 지점을 정해주었다

결과물은 나쁘지 않게 잘 나온 것 같았다

다만 여기서 아이디어를 얻어 크나큰 실패를 맛보게 되는데...

공격 판정

Trail 파티클을 NotifyState를 이용해 실행하는 것을 보고, 공격 판정을 이와 비슷하게 노티파이 스테이트를 이용해 하면 어떨까

라는 생각을 하고 실행해보았다

NotifyState를 상속받는 UAnimNotifyState_AttackCheck 함수를 만들고, 함수의 Tick 부분에 Sweep 을 통해 충돌처리를 진행하였다

UAnimNotifyState_AttackCheck.cpp

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

#include "Game/AnimNotifyState_AttackCheck.h"
#include "Engine/DamageEvents.h"

void UAnimNotifyState_AttackCheck::NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime,
    const FAnimNotifyEventReference& EventReference)
{
    Super::NotifyTick(MeshComp, Animation, FrameDeltaTime, EventReference);

    APawn* MeshOwner = Cast<APawn>(MeshComp->GetOwner());

    if (::IsValid(MeshOwner))
    {
        FHitResult OutHit;
        FCollisionQueryParams Params;
        Params.AddIgnoredActor(MeshOwner);
        bool bResult = MeshOwner->GetWorld()->SweepSingleByChannel
        (
            OutHit,
            MeshComp->GetSocketLocation(StartSocket),
            MeshComp->GetSocketLocation(EndSocket),
            FQuat::Identity,
            ECollisionChannel::ECC_Visibility,
            FCollisionShape::MakeSphere(20.0f),
            Params
        );
        if (bResult)
        {
            
            APawn* HitTarget = Cast<APawn>(OutHit.GetActor());
            if (::IsValid(HitTarget))
            {
                FDamageEvent DamageEvent;
                HitTarget->TakeDamage(1, DamageEvent, MeshOwner->GetController(), MeshOwner);
            }
        }

#if ENABLE_DRAW_DEBUG
        DrawDebugSphere(MeshOwner->GetWorld(), (MeshComp->GetSocketLocation(StartSocket) + MeshComp->GetSocketLocation(EndSocket)) / 2, 20.0f,
            12, bResult? FColor::Green : FColor::Red, false, 5.0f);
#endif
    }
}

실행될 MeshComp의 Owner를 찾아 폰으로 캐스팅해주었고, 검출한 대상을 캐스팅해 TakeDamage 함수를 실행시켜주었다

TakeDamage 함수는 Enemy에서 Override해주었다

IFEnemy.cpp

float AIFEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);

    AnimInstance->React(this, DamageCauser);

    return 0.0f;
}

React 함수는 AnimInstance에서 선언하며, 두 액터의 위치를 내적하여 공격 판정을 뒤에서 받을지, 앞에서 받을지 결정짓는다

구현 후 모션에 맞게 노피타이 State를 지정해주었다

완성된 결과는 다음과 같다

결과를 확인하고 굉장히 마음에 들었다

다만 적에게 실험하고서 큰 문제가 있다는 것을 깨닳았다

바로 이렇게 공격판정을 받지 않고 교묘하게 피해질 수 있다는 점이었다...

현재는 수정을 해야할지, 새로운 방식을 찾아야할지 고민 중이다

적 자동 타켓

적이 근처에 있을때 자연스럽게 적의 방향으로 보정해주는 식을 추가했다

IFCharacter.cpp

void AIFCharacter::WeakAttack()
{
	if (::IsValid(Target) && !AnimInstance->GetAimState())
	{
		float DotProduct = FVector::DotProduct(GetActorForwardVector(), Target->GetActorLocation() - GetActorLocation());
		if (DotProduct > 0.4)
		{
			Target->WarpPoint->SetWorldLocation(Target->GetActorLocation() + (Camera->GetComponentLocation() - Target->GetActorLocation()).GetSafeNormal() * 75);
			FVector Direction = Target->WarpPoint->GetComponentLocation() - Camera->GetComponentLocation();
			FRotator TargetRotation = Direction.Rotation();
			Controller->SetControlRotation(FRotator(Controller->GetControlRotation().Pitch, TargetRotation.Yaw, Controller->GetControlRotation().Roll));
		}
	}

	AnimInstance->PlayWeakAttackMontage();
}

이번에도 내적을 활용해 적을 어느정도 바라보고 있는 상황이라면 적쪽으로 카메라를 회전시키도록 구현하였다

완성된 모습은 다음과 같다

개선할 점

먼저 충돌방식에 대해 더욱 개선해야 할 것 같다

일단 현재는 노티파이 State가 tick으로 돌기 때문에, 타격이 여러번 이뤄지게 되는데,

이를 한 공격에 한번만 반응하도록 설정을 해주어야 개선하고자 한다

물론 이 과정에서 Notify State를 통해 충돌을 관리하는것이 맞는지 다시한번 고민해볼 것 같다

다음으로는 현재 애니메이션이 앞에서 공격받을때와 뒤에서 공격받을때, 2가지 밖에 없기 때문에, 주어진 한계 내에서

더욱 자연스럽게 피격되도록 고민해볼 것이다

profile
토비폭스가 되고픈 게임 개발자

0개의 댓글