언리얼엔진(UE)

[UE] 몬스터 AI 구현 #8 (원거리 공격 투사체 발사 및 공격 이펙트)

2h1824 2025. 3. 5. 23:36

1. 투사체 발사 로직

RangedEnemy.h

// Fill out your copyright notice in the Description page of Project Settings.
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once

#include "CoreMinimal.h"
#include "BaseEnemy.h"
#include "RangedEnemy.generated.h"

//전방선언
class ABaseBullet;
/**
 * 
 */
UCLASS()
class STARHUNT_API ARangedEnemy : public ABaseEnemy
{
	GENERATED_BODY()
public:
	ARangedEnemy();

	virtual void SetMovementSpeed(const EMovementSpeed Speed) override;

	virtual void Attack() override;

	UFUNCTION(BlueprintCallable, Category="Attack")
	void Fire();

protected:
	// 에디터에서 총알 종류 선택 가능
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gun|Bullet")
	TSubclassOf<class ABaseBullet> BulletClass;
};

RangedEnemy.cpp

// Fill out your copyright notice in the Description page of Project Settings.
// Copyright Epic Games, Inc. All Rights Reserved.

#include "RangedEnemy.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "BaseBullet.h"
#include "Kismet/GameplayStatics.h"
#include "AIEnum.h"
#include "GameFramework/ProjectileMovementComponent.h"

ARangedEnemy::ARangedEnemy()
{
	Score = 150;
	Health = 300;
	MaxHealth = Health;
	Power=10;
	AttackRadius=600.0f;
	DefendRadius=600.0f;
}

void ARangedEnemy::SetMovementSpeed(const EMovementSpeed Speed)
{
	Super::SetMovementSpeed(Speed);
	if (UCharacterMovementComponent* MovementComp = GetCharacterMovement())
	{
		switch (Speed)
		{
		case EMovementSpeed::Idle:
			MovementComp->MaxWalkSpeed = 0.0f;
		case EMovementSpeed::Walking:
			MovementComp->MaxWalkSpeed = 200.0f;
		case EMovementSpeed::Jogging:
			MovementComp->MaxWalkSpeed = 300.0f;
		case EMovementSpeed::Sprinting:
			MovementComp->MaxWalkSpeed = 500.0f;
		default:
			break;
		}
	}
}

void ARangedEnemy::Attack()
{
	Super::Attack();
	Fire();
}

void ARangedEnemy::Fire()
{
	if (!BulletClass) return;
	// 캐릭터 메시의 특정 Bone 위치에서 총알 생성
	FVector Start=GetMesh()->GetBoneLocation("pistol_cylinder",EBoneSpaces::WorldSpace);
	FRotator SpawnRotation=GetActorRotation();

	if (ACharacter* Player=Cast<ACharacter>(GetWorld()->GetFirstPlayerController()->GetPawn()))
	{
		// 총알 생성 지점과 플레이어 위치를 통해 방향 벡터 구하고 정규화
		FVector Direction=(Player->GetActorLocation()-Start).GetSafeNormal();
		//DrawDebugLine(GetWorld(),Start,Start+Direction*5000,FColor::Red,false,1.0f,0,2.0f);
		//총알 생성
		if (ABaseBullet* Bullet=GetWorld()->SpawnActor<ABaseBullet>(BulletClass,Start,SpawnRotation))
		{
			//총알 데미지 설정
			Bullet->SetBulletDamage(Power);
			if (UProjectileMovementComponent* MovementComp=Bullet->GetProjectileComp())
			{
				//총알이 Velocity 방향을 따르도록 설정 및 Velocity 값 방향벡터와 속도 이용해 설정
				MovementComp->bRotationFollowsVelocity=true;
				MovementComp->Velocity=Direction*MovementComp->GetMaxSpeed();
			}
		}
	}
}
  • 몬스터 메시의 총구의 뼈 이름을 통해 위치 절적한 위치 선정
  • 해당 뼈의 위치와 플레이어 캐릭터의 위치 벡터를 이용하여 방향벡터 계산
  • 방향 벡터를 정규화
  • SpawnActor를 통한 총알 생성 및 기본 데미지 설정
  • 총알이 Velocity의 방향으로 날아가도록 하는 옵션(bRotationFollowsVelocity) 설정
  • UProjectileMovementComponent의 Velocity값을 위에서 구한 방향벡터에 기본 설정된 MaxSpeed를 곱하여 설정
    ㅡ> 총구에서 플레이어 방향으로 기본 설정된 속력으로 발사
  • BaseBullet(발사체) 클래스에서 데미지 처리

2. 공격 모션 이펙트 추가

  • 원하는 프레임에서 멈추고 Notify Track 추가

  • 원하는 트랙에서 우클릭하여 Sound는 'Play Sound', Effect는 'Play Particl Effect'로 Notify 추가

  • 원하는 이펙트 선택
  • 특정 구간 반복 재생시키면서 원하는 위치에서 Effect가 나타날 수 있도록 Transform 값 조절
  • Sound의 경우 원하는 파일 선택 및 볼륨 조절

 

3. 정리

완료

  • 원거리 적의 공격 모션 Sound, Effect 추가
  • 원거리 적 공격 시 발사체 생성 및 원하는 방향으로의 발사
  • 총알의 데미지 처리

예정

  • AI의 Behavior Tree 수정
  • 버그 픽스
  • Hit Reaction 추가

 


참고자료