Unity

2D RPG - 콤보 공격 만들기

뽀또치즈맛 2026. 1. 7. 11:40

 

 

복잡한 상태를 하위 계층 구조로 나누어 관리할 수 있는 sub state machine을 사용하여 콤보 공격을 구현하였다.

 

콤보 공격에 사용된 sub state machine의 내부 구조는 다음과 같다.

 

이런식으로 인덱스가 같으면 다음 인덱스로 넘어가게끔 한 것이다.

 

아래는 콤보 구현 방식 코드이다.

using UnityEngine;

public class Player_BasicAttackState : EntityState
{

    private float attackVelocityTimer;

    private const int FirstComboIndex = 1;
    private int comboIndex = 1;
    private int comboLimit = 3;
    public Player_BasicAttackState(Player player, StateMachine stateMachine, string animBoolName) : base(player, stateMachine, animBoolName)
    {

    }

    public override void Enter()
    {
        base.Enter();

        ResetComboIndexIfNeeded();

        anim.SetInteger("basicAttackIndex", comboIndex);
        ApplyAttackVelocity();
    }

    public override void Update()
    {
        base.Update();
        HandleAttackVelocity();

       if (triggerCalled)
        {
            stateMachine.ChangeState(player.idleState);
        }
    }

    public override void Exit()
    {
        base.Exit();
        comboIndex++;
    }

    private void ApplyAttackVelocity()
    {
        attackVelocityTimer = player.attackVelocityDuration;
        player.SetVelocity(player.attackVelocity.x * player.facingDir, player.attackVelocity.y);
    }

    private void HandleAttackVelocity()
    {
        attackVelocityTimer -= Time.deltaTime;

        if (attackVelocityTimer < 0)
        {
            player.SetVelocity(0, rb.linearVelocity.y);
        }
    }

    private void ResetComboIndexIfNeeded()
    {
        if (comboIndex > comboLimit)
            comboIndex = FirstComboIndex;
    }
}

 

 

콤보 구현에 만약 시간차를 구해서 특정 시간을 넘으면 콤보가 연결되지 않도록 하는 것은 마지막 부분을 다음과 같이 고치면 된다.

    private void ResetComboIndexIfNeeded()
    {
        if (Time.time > lastTimeAttacked + player.comboResetTime)
        {
            comboIndex = FirstComboIndex;
        }
        if (comboIndex > comboLimit)
        {
            comboIndex = FirstComboIndex;
        }
    }

 

 

콤보 공격 중 방향 변환하기

 

공격 state로 전환되어 Enter에서

공격 중에 (콤보 어택 플레이 중에) 만약 moveInput이 들어왔다면,

이전에 facingDir을 기준으로 하지 않는다.

 

moveInput에 대한 Dir을 기준으로 삼은 뒤

해당 방향을 공격 방향으로 정의한다.

이후 플레이어의 velocity를 attackDir에 맞게 적용시킨다.

    public override void Enter()
    {
        base.Enter();
        comboAttackQueued = false;
        ResetComboIndexIfNeeded();

        attackDir = player.moveInput.x != 0 ? ((int)player.moveInput.x) : player.facingDir;


        anim.SetInteger("basicAttackIndex", comboIndex);
        ApplyAttackVelocity();
    }


...
...


	private void ApplyAttackVelocity()
    {
        Vector2 attackVelocity = player.attackVelocity[comboIndex - FirstComboIndex];

        attackVelocityTimer = player.attackVelocityDuration;
        player.SetVelocity(attackVelocity.x * attackDir, attackVelocity.y);
    }