게임개발일지/리그오브워치

[리그오브워치개발일지] #6 미니언 AI - 자동공격

김진우 개발일지 2023. 10. 4. 19:45

Git

레포지토리 주소 : https://github.com/kjinwoo12/UE5Game_LeagueOfWatch
기준 브랜치 : 6_MinionAIAttack

개발내용 정리

이전글에서는 미니언 자동이동을 만들었다. 아래 개발 기능 목록에서 개발 완료한 것은 취소선으로 표시하거나 본문 길이를 위해 삭제했다.

  • 게임진행 규칙 :게임이 진행되는 동안 세 개의 공격로에서 각각 30초 간격으로 미니언 6마리가 생성되고, 적 기지를 향해 이동하면서 적 진영의 오브젝트를 공격한다.
    • 미니언
      • 팀 구별 기능
      • 자동생성
        • 게임 진행시간 기록
      • 자동이동
      • 체력
      • 자동공격
        • 공격 이펙트
        • 피격 이펙트
    • 진영 소속 오브젝트 (예: 포탑)
  • 체력 규칙 : 체력이 있는 모든 오브젝트는 체력이 0 이하가 되면 파괴되거나 죽는다.
  • 게임 승리 규칙 : 게임의 최종 목표는 적 진영 중요 건물(이하 "넥서스")을 파괴하는 것이다.
    • 넥서스
      • 체력

이번 글에서는 체력 뿐 아니라 방어력 요소도 추가했다.

목표

이전글에서는 미니언에 자동이동 AI를 만들었고, 이번 글에서는 여기에 자동공격 기능을 추가하려고 한다. 미니언 체력, 공격 이펙트, 피격 이펙트를 만들고 난 다음에 AI가 적을 만나면 자동으로 상대를 공격하는 기능을 완성하는 것이 목표다.

본문

피격

언리얼 엔진에서는 데미지에 관한 이벤트와 데미지 함수를 제공한다. 피격에 관련된 이벤트는 아래 링크를 참고해 사용한다.

미니언 액터에 HP 변수를 추가 후 피격 이벤트에서 받은 데미지만큼 감소시키면 피격판정 기능은 완성이다. 여기에 방어력으로 인한 피해 감소 등 부가적인 기능을 추가하면 된다. 나같은 경우에는 BlueprintFunctionLibrary로 방어력 공식 코드를 추가하고 데미지 타입에 인터페이스를 추가해서 데미지 타입마다 다른 데미지 공식을 가질 수 있도록 만들었다. 블루프린트에 직접 하거나 미니언 부모 클래스를 만들어 함수를 추가하지 않은 이유는 미니언 뿐 아니라 다른 캐릭터에서도 피격 판정을 사용할 여지가 있기 때문이다.

블루프린트 함수 라이브러리 추가

CombatFormulaFunctionLibrary.h

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

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "CombatFormulaFunctionLibrary.generated.h"

/**
 * 
 */
UCLASS()
class LEAGUEOFWATCH_API UCombatFormulaFunctionLibrary : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()

    UFUNCTION(BlueprintCallable, Category="CombatFormula")
    static float ArmoredDamageFormula(float OriginalDamage, float Armor);
};

CombatFormulaFunctionLibrary.cpp

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

#include "Characters/CombatFormulaFunctionLibrary.h"

float UCombatFormulaFunctionLibrary::ArmoredDamageFormula(float OriginalDamage, float Armor)
{
    float resultDamage = OriginalDamage;

    if (Armor >= 0)
    {
        OriginalDamage /= 1 + Armor * 0.01;
    }
    else
    {
        OriginalDamage /= 2 - 1 / (1 - Armor * 0.01);
    }

    return resultDamage;
}

능력치 구조체 추가

SCharacterStat

데미지 타입 인터페이스 추가

BPI_DamageType

데미지 타입 두 종류 추가

데미지 타입에는 데미지 타입 인터페이스를 추가한다.

BP_DamageType_AttackDamage

BP_DamageType_AbilityDamage

BP_Minion

공격

리그오브레전드에는 네 종류의 미니언이 있고, 두 가지 공격 방식이 존재한다. 근접 미니언과 슈퍼 미니언의 근접공격, 원거리 미니언과 대포 미니언의 원거리 투사체 공격이 있다. 이 글에서는 원거리 공격을 투사체 대신에 근접 공격과 동일하게 데미지를 곧바로 입히는 방식을 다룬다. 공통적인 부분은 데미지 수치를 직접 호출하는 함수로, 언리얼 엔진에서는 캐릭터의 데미지 이벤트를 호출하는 함수를 지원한다. 데미지 추가 함수 공식 문서 링크를 눌러 어떤 함수가 있는지 확인할 수 있다.

투사체를 이용하지 않는 미니언의 근접공격과 원거리공격은 기술적으로 동일하다. 사정거리가 길면 원거리 공격이고 짧으면 근거리 공격이다. 사거리 변수를 추가한 다음에 사정거리 밖에 적이 존재하면 가까히 다가가고, 사정거리 안에 적이 존재하면 공격하도록 구현했다.

비헤이비어 트리

BlackBoard Keys
Behavior Tree

데코레이터

  • IsValidAttackTarget
    • Blackboard
    • 관찰자 노티파이 : On value Change
    • 관찰자 중단 : Lower Priority
    • 키 쿼리 : Is Set
    • 블랙보드 키 : IsAttackTargetInRange
  • IsAttackTargetInRange
    • Blackboard
    • 관찰자 노티파이 : On value Change
    • 관찰자 중단 : Lower Priority
    • 키 쿼리 : Is Set
    • 블랙보드 키 : IsValidAttackTarget

테스크

자동 공격을 위한 새로운 테스크도 두 개 추가했다. BTTask_Minion_StopMovementBTTask_Minion_AttackTarget이다.

BTTask_Minion_StopMovement

BTTask_Minion_AttackTarget

BP_Minion

미니언 블루프린트에는 데미지 적용, 사정거리 검사, 공격 시도, 공격 딜레이 기능이 추가되었다. 피격 시 HP가 0 이하가 되면 액터를 파괴 처리한다.

이벤트그래프

ApplyAttackDamage : 데미지 적용

IsInAttackRange : 사정거리 검사

DoAttack : 공격 시도

TickDecreaseAttackDelay : 공격 딜레이 Tick

AIC_Minion

개체 인식 AI를 기반으로 적 개체를 공격 대상 대기열에 추가 또는 제거한다. 공격 대상 개체를 공격하거나, 공격 대상이 없을 경우에는 PatrolPoint로 움직이도록 블랙보드에 값을 전달한다. 공격 대상을 판별하는 방법은 원하는 액터에 태그를 추가하고, AI 인식 컴포넌트에서 감지된 액터가 태그를 가지고 있는지 검사하는 것이다. 나의 경우에는 MinionAttackTarget를 태그로 정해서 추가했다. BP_Minion에도 태그를 추가해서 서로 공격할 수 있도록 만들었다.

이벤트그래프

InitializeBlackboardKeys : 블랙보드 키 초기화

IsEnemyActor - Pure 함수 : 적 개체 검사

AddAttackTarget : 공격 대상 대기열 추가

RemoveAttackTarget : 공격 대상 대기열에서 액터 제거

결과

미니언은 사정거리 안에 들어온 적에게 1초에 1번 데미지 50의 공격을 한다. 미니언 사거리는 1000으로 설정했다. 만약 근접 미니언을 만들고 싶으면 사거리를 원하는 만큼 낮추면 될 것이다. 아래 영상에서는 미니언이 서로 공격하다가 패배한 미니언은 파괴처리되고, 승리한 미니언은 공격 대상이 사라져 공격을 멈추고 다시 PatrolPoint로 이동하는 모습을 확인할 수 있다.

다음

다음 글에서는 미니언과 함께 AOS 장르의 필수라고 할 수 있는 넥서스와 타워를 다룰 예정이다. 넥서스가 파괴되었을 때 게임을 승리 또는 패배하고, 근처에 적이 있을 때 고정된 자리에서 적을 공격하는 타워를 만들 것이다.