플밍

유니티 액션겜 개발일지 - 캐릭터 컨트롤러 구조개선(2)

에페아 2021. 4. 28. 22:24

gimchicchige-mukgoshipda-1223.tistory.com/39

 

유니티 액션겜 개발일지 - 캐릭터 컨트롤러 구조개선(1)

최근에 디자인패턴 책을 보며 공부를 시작했다 결과물만 나오면 장땡일 수준은 한참 지났으니까 구조에 대해서도 공부를 제대로 해야겠다라는 마음으로. 그래서 한번 배운거 써먹어보기위해

gimchicchige-mukgoshipda-1223.tistory.com

이전 글에서 이어서 만드려고 한다

 

패턴 책 보고 내가 이전에 만들어놓은 코드를 보니까 머리가 아프다

수정해야될 곳이 생각보다 꽤많다

솔직히 만든것도 별로없는거 그냥 코드 싹 지우고 새로 짤까 싶은 욕구도 들지만

유지보수 연습하는거라 생각하고 수정해보자

 

일단 첫번째로 드는 생각이

캐릭터를 FSM으로 구현해놔서 키 입력이 들어간다고 해서 무조건 실행시키면 안된다

입력이 들어가면 정말 딱 해당 입력 정보만 그대로 전달해줘야된다

어떤 키가 어떤식으로 눌렸는지에 대해서 말이다

 

이전 구조에서는 그냥 fsm 내부에서 컨트롤러를 참조해가지고 썼으니까 이런 문제가 없었는데

지금은 컨트롤러에서 fsm에 신호를 보내는 방식이다보니 흠... 머리가 안돌아간다

 

결국 상태 클래스에 어떤 키를 눌렀는지에 대한 열거형을 하나 더만들어서 받아오기로 했다

이동키 받아오는거 따로만든 이유는 사실상 키 4개(상하좌우)가 한 기능을 위해 쓰이는데 그거 일일이 키 하나하나 처리하는것보다 예외로 빼서 처리하는게 더 나을것같았기 때문이다

 

#region Actor Actions
    public override void MovingCheck(Vector3 moveDir) => _nowAction.CheckMoveDir(moveDir);

    public override void OnNormalAtk(InputState state) => _nowAction.CheckInputKeys(InputKey.NORMALATK, state);

    public override void OnDodge(InputState state) => _nowAction.CheckInputKeys(InputKey.DODGE, state);
    #endregion

캐릭터 매니저에서는 이런식으로 인터페이스를 구현해줬다

_nowAction가 현재 상태인데, 현재 상태에다가 키 입력이 들어왔다는걸 알리는 식이다

 

그럼 이제 각 상태클래스에 들어가서 받아온 신호를 기반으로 수정해야한다

 

일단 가장 쉬운 Idle 상태부터 고치기로 했다

이렇게 되있던 기존 구조를

이렇게 바꿨다

차이점이라고 한다면 위의 구조는 상태클래스에서 컨트롤러에 접근한거고 

아래의 구조는 외부에서 받아온 인자값을 가지고 처리를 하도록 바뀐 것.

 

 

public override void CheckInputKeys(InputKey key, InputState state)
    {
        if (key == InputKey.DODGE && state == InputState.PRESSED) _owner.ChangeAction("Dodge");
        if (key == InputKey.NORMALATK && state == InputState.PRESSED) _owner.ChangeAction("Atk");
    }

    public override void CheckMoveDir(Vector3 dir)
    {
        if (dir == Vector3.zero)
            _owner.ChangeAction("Idle");
    }

이동 상태도 똑같이 고쳐주었다

 

이제 회피랑 공격이 남았다

이 둘이 좀 힘들었는데

이전에 있던 두 상태는 그냥 입력만 들어오면 바로 상태가 바뀌어도 되는 상황이었다

하지만 이 둘은 입력이 들어온다고 해서 바로 처리되면 안되는 애들이고, 키 입력을 여러 군데에서 체크했기 때문에 CheckInputKeys 안에 다 넣어주기 위해서는 상태코드 내에서도 어느정도의 수정이 필요했다

public override void CheckInputKeys(InputKey key, InputState state)
    {
        //다음 공격 예약
        if (key == InputKey.NORMALATK && state == InputState.PRESSED)
            if (_nextAtkOk && !_isNextAtk) _isNextAtk = true;

        //회피(공격 캔슬 가능)
        if (key == InputKey.DODGE && state == InputState.PRESSED && _stat._isDodgeOk)
            _owner.ChangeAction("Dodge");
    }

    public override void CheckMoveDir(Vector3 dir)
    {
        if (!_isNextAtk && _finishAtk)
        {
            if (dir == Vector3.zero) _owner.ChangeAction("Idle");
            else _owner.ChangeAction("Moving");
        }
    }

공격 상태에서의 인터페이스 구현부이다

이전에서 ~~상황일 때 컨트롤러를 참조해서 키입력을 체크해가지고 실행을 시켰다면

이제는 '~~상황' 을 bool값이든 뭐든 해서 인터페이스 내부로 끌고와가지고 실행시키도록 만들었다

 

회피도 마찬가지로

public override void CheckMoveDir(Vector3 dir)
    {
        if (_finishCheck)
        {
            if (dir == Vector3.zero) _owner.ChangeAction("Idle");
            else _owner.ChangeAction("Moving");
        }

        if (_dodgeDir == Vector3.zero)
        {
            SetDodgeData(dir);
        }
    }

저 _finishCheck 가 회피가 끝났을 경우를 판단하기 위해 새로 만든 bool형 필드이다

그리고 추가로, 회피상태일때는 다른 키 입력을 전혀 받지 않기때문에 굳이 CheckInputKeys를 구현하지 않아도 된다

 

 

이제 다 됬다

잘 돌아가는지 살펴보자

잘 돌아가는 것 같다

나름 성공적인듯 하다

 

다음은 이제 공격을 한번 손 볼 예정

3타까지 있는게 좀 부족한 것 같기도 하고 애니메이션 타이밍도 뭐어어언가 좀 부족하다

거기다 이펙트도 안나오고, 공격할때 조금의 움직임도 없이 제자리에서 공격하는것도 좀 바꿔야할 것 같다

반응형