1 minute read

유닛 이동 구현

어제 만든 이동 기능을 UserUnitController로 옮기고 진행했습니다. 이제 UserInputManager의 기능은 순수히 InputAction들을 실행시키기만 합니다.

private void OnEnable()
{
    mouseLeftClick = playerInputActions.User.MouseLeftClick;
    mouseRightClick = playerInputActions.User.MouseRightClick;
    mouseDrag = playerInputActions.User.MouseDrag;
    hold = playerInputActions.User.Hold;
    readyToAttack = playerInputActions.User.ReadyToAttack;

    mouseLeftClick.Enable();
    mouseRightClick.Enable();
    mouseDrag.Enable();
    hold.Enable();
    readyToAttack.Enable();
}

private void OnDisable()
{
    mouseLeftClick.Disable();
    mouseRightClick.Disable();
    mouseDrag.Disable();
    hold.Disable();
    readyToAttack.Disable();
}

UserUnitController는 유저가 유닛을 컨트롤 할 때 필요한 기능 전반을 담당합니다. 선택한 유닛들을 이동시키는 기능도 포함됩니다. 선택한 유닛 목록을 관리하여 우클릭 시 각 유닛들에게 해당 위치로 이동하는 명령을 내립니다. 유닛끼리 해당 위치로 가려고 충돌이 일어날 텐데, 단순히 offset 값을 유닛 수가 늘어날 때마다 조금씩 주는 것으로 해결했습니다.

public void OnMouseRightClick(InputAction.CallbackContext context)
{
    if (selectedUnits.Count > 0)
    {
        MouseStartPos = mouseDrag.ReadValue<Vector2>();
        Vector2 worldMousePos = Camera.main.ScreenToWorldPoint(MouseStartPos);
        targetPositionMarker.gameObject.SetActive(true);
        targetPositionMarker.SetPosition(worldMousePos);
        float offset = 0;
        foreach (var unit in selectedUnits)
        {
            ((IMovable)unit).Move(worldMousePos, offset);
            offset += 1.0f;
        }
    }
}

이 작업을 하면서 인터페이스를 단순히 형변환만 해주면 해당 인터페이스가 속한 클래스의 기능들이나 같이 상속받은 인터페이스의 기능도 다 함께 사용할 수 있다는 것도 배웠습니다.

참고로 네비게이션 기능은 NavMeshPlus의 2D 네비게이션 기능을 활용하여 이동을 구현했습니다.

스크린샷 2024-07-02 195547

유닛을 선택하고 우클릭하면 스타크래프트나 워크래프트처럼 해당 자리에 초록 점이 잠깐 나타나고 그 자리로 이동합니다. 물론 이동은 유닛에서 구현했습니다.

public void MoveToTarget(Vector2 target, float offset)
{
    isHold = false;
    agent.stoppingDistance = offset;
    agent.SetDestination(target);
}

또한, H 키를 누르면 이동 중에 멈추고 홀드되는 기능도 추가했습니다. 유닛이 이동을 중지하고 대기 상태로 전환됩니다.

public void HoldPosition()
{
    isHold = true;
    agent.isStopped = true;
}

느낀 점

이제 A 키를 누르면 공격 표시가 마우스를 따라다니다가 좌클릭하면 해당 유닛을 공격하거나, 해당 위치로 공격하며 이동하게 만들 계획입니다. 이를 대략 정리해보면 다음과 같습니다:

  1. A 누르기 -> 타겟 지정 -> 타겟 공격
  2. A 누르기 -> 땅 지정 -> 이동 -> 이동 중 적 발견 시 중지 및 공격 -> 적 이동 시 추적 -> 적 사살 시 다시 이동
  3. 정지 상태에서 적 감지 -> 공격 -> 적 이동 시 추격

공격 하나를 구현하는데 신경 쓸 것이 많지만, 내일 완료할 수 있을 것 같습니다. 생각보다 이동을 구현하는 것이 어렵지 않아서 다행입니다. 다만 UserUnitController가 너무 많은 기능을 담당하는지 고민이 되는데, 이는 프로토타입을 제작한 후 리팩토링 시간을 가지면 해결할 수 있을 것 같습니다.