Profile

대혐수의 뒷동산

대혐수

[유니티]주먹구구 탐정게임 만들기 - 대화가 다 종료된 후 실행하기

  지금 만드는 건, 탐정게임의 필수요소라고 할 수 있는 "탐문모드"다.

 

  대화를 이어나가면서 새로운 증거를 찾거나, 거짓말을 밝혀내는 등, 탐정장르에서 가장 재밌는 순간이 인물을 탐문할 때 나오기 마련이다.

 

  그런데 날 막아선 건 시스템 구현 자체가 아니라, 전혀 다른 부분에서였다.

  바로 대사가 다 나오기도 전에 탐문모드 인터페이스가 나와버리는 것...

 

  내가 구상한 탐문모드 진행방식은 이랬다.

 

  1."대화하기"커맨드 버튼을 누른다.

  2.현재 위치에 대화 가능한 인물이 있다면, 탐문모드에 돌입하게 된다.

  3.탐문모드에 돌입하기 전, 간단한 인트로덕션 대화가 나온다. "여어, 탐정. 또 만났군. 아직 물어볼 것이 남았나?"같은..

  4.탐문 인터페이스가 나오고.....

 

  그런데 3단계가 다 끝나기도 전에, 아니, 3단계가 시작하자마자 탐문 인터페이스가 나와버리는 한심한 사태가 벌어진다.

 

 

(참고로, 대화모드는 아래의 고마운 강좌를 보고 구현했다)

 

 

 

  사실 이 문제는 이전에 구현한 다른 기능들에서도 문제가 됐던 부분이라, 개선해야겠다는 생각은 전부터 갖고 있었다. 그러나 어떻게 해야 할지 모르겠어서 미뤄두다가 이번에야말로 손을 보기로 했는데....

  "유니티 게임 일시정지" "유니티 함수 다음 함수" "unity function after function is finished"등등...여러가지로 검색해봐도 내 상황에 꼭 맞는 강좌나 도움말을 찾을 수 없었다.

 

  왜 그럴까 생각해보니, 아무래도 게임 내용과 그 구현방식에 따라 케이스 바이 케이스이고, 어떤 일반적인 방법이 있지는 않아서일 것 같았다.

 

  그렇다면 내가 처한 문제 상황은 다음 둘 중 하나일 것이다.

 

  1.사실 엄청 간단한 방법이 있는데 내가 멍청해서 생각을 못 해내고 있다.

  2.처음부터 지금까지 주먹구구로 만든 게임 구조를 다시 뒤집어까야지 안 그러면 방법이 없다.

 

  2번 가설대로일까봐 잠을 못 이루는 며칠...자존감과 의욕이 바닥을 치는데...

 

  그나저나 강좌와 도움말을 찾아볼 때 가장 많이 나오는 건 invoke를 이용한 시간지연이었다.

  물론 invoke자체는 내 상황에 적용할 것이 아니지만, 코딩할 때 늘 그렇듯 갑자기 invoke가 힌트를 주기 시작했다.

 

  인트로덕션 대화가 끝난 다음에 탐문모드 실행 매서드를 실행시킬 궁리를 하지 말고,

  인트로덕션 대화가 끝나면서 탐문보드를 실행하라는 명령을 내리면 되는 것 아닐까?

 

  늘 그렇듯이, 지극히 간단한 걸 가지고 끌탕을 하고 있었다...

  이러니 내가 한심한 놈을 벗어나질 못하지.

 

  작전을 다음과 같이 짰다.

 

  1.탐문 커맨드 버튼을 누른다.

  2.현재 장소에서 대화 가능한 상대의 탐문 데이터가 로드된다.(여기까지는 이미 구현해놓은 부분)

  3.탐문데이터의 인트로덕션 대화를 실행하면서, 대기중인 액션으로 탐문모드를 지정한다.

  4.대화모드를 관장하는 "DialogueProjecter"는 게임을 논인터랙티브 상태로 설정한다.

  5.논인터랙티브 상태를 관장하는(?) 스크립트 "NonINteractiveExecuter"는 update()에서 논인터랙티브 모드가 끝났는가의 여부를 체크하기 시작한다.

  6.대화가 모두 종료되면 논인터랙티브 상태를 해제한다.

  7."NonINteractiveExecuter"는 논인터랙티브 상태가 종료되었음을 확인하고 대기중인 액션인 탐문모드를 실행한다.

 

  3번부터 하나하나 살펴보면...

 

3.탐문데이터의 인트로덕션 대화를 실행하면서, 대기중인 액션으로 탐문모드를 지정한다.

  대기중인 액션은 "NonINteractiveExecuter"의 정수형 변수에 "1"을 넣는 것이다.

 public int awaitingOrder = 0; //논인터랙티브 모드가 종료되면 실행할 액션의 번호
  //※ 0 : 액션없음 / 1 : 탐문모드

  아직까지는 탐문모드만 지정되어있지만, 앞으로 다른 데에도 똑같이 활용할 수 있지 않을까 기대중. "대화가 나온다 -> 실행해야 할 게임요소가 나온다" 라는 진행은 대화형 어드벤처의 기본이니까.

 

  한편 탐문모드가 처리되는 스크립트인 "ActionManager"에서 탐문 커맨드버튼이 눌리면 탐문모드 변수를 1로 바꾸도록 조치했다.

 

public void BT_Talk()
    {
        
        if (readyForTalkPersonFileName == "0") //이 장소에 대화상대자가 없다는 의미이다.
        {
            //대화하기 없음 대사 나옴
            //메인액션모드 재가동
        }
        else 
        {            
            //일단 대화하기가 시도되면 인트로 대사가 나온다.
            CentralHub.Instance.NonINteractiveExecuter.awaitingOrder = 1; //탐문모드를 대기시켜놓음
        }
    }

  (이번 포스팅 주제와 상관 없는 부분은 주석만 남기고 지웠당. 읽기 편하시라고...)

 

4.대화모드를 관장하는 "DialogueProjecter"는 게임을 논인터랙티브 상태로 설정한다.

  논인터랙티브 상태라고 하면 거창해보이지만.. ㅋㅋ 그냥 "NonINteractiveExecuter"의 bool변수 " InNonInteractiveMode"를 true로 지정하는 것이다.

 

 public void reLoadingDialouge(NonInteractiveDialogueBase dangan)  //출력할 대사데이터를 큐로 저장하고 논인터대화가동함
    {
        CentralHub.Instance.NonINteractiveExecuter.InNonInteractiveMode = true; //논인터랙티브모드 돌입
        //대화창열기
        //기존에 남아있던 대사데이터를 다 날린다.

        //foreach로 새 대사 데이터를 Equeue한다.
        
        ProjectingDialogue();
    }

 

  "reLoadingDialouge" 매서드는 scriptable object로부터 대사 데이터를 받아온 후, 이를 출력하는 "ProjectingDialogue" 매서드를 실행하는 놈이다(그나저나 내가 매서드와 변수와 스크립트 이름 짓는 센스는 좀..봐주세요 어차피 혼자 만드는 거라고 심심해서 저렇게 함).

  보시다시피 매서드가 실행되자마자 InNonInteractiveMode를 true로 설정한다.

 

5.논인터랙티브 상태를 관장하는(?) 스크립트 "NonINteractiveExecuter"는 update()에서 논인터랙티브 모드가 끝났는가의 여부를 체크하기 시작한다.

  우선 "NonINteractiveExecuter"에는 다음과 같이 했다.

 void Update()
    {
        if (awaitingOrder > 0) //즉 어웨이팅 오더가 걸려있을 때 
        {
            if (!InNonInteractiveMode) ExecuteAwaitingOrder(awaitingOrder); //논인터랙티브모드가 끝났음을 감지하고 어웨이팅오더를 실행한다.
        }
        
    }

    void ExecuteAwaitingOrder(int order)
    {
        switch (order)
        {
            case 1:
                CentralHub.Instance.ActionController.PrepareIntero();
                awaitingOrder = 0; //어웨이팅 오더 리셋
                break;
        }
    }

  여기서 "PrepareIntero()" 는 심문 인터페이스를 열고, 불러온 심문 데이터에 따라 심문 가능한 주제를 버튼으로 만들어주는 매서드다.

 

  그리고 "DialogueProjecter"에서 대화모드를 종료하는 매서드에는 당연히...  

public void NonInteractiveDialogueModeOff()
    {
        //대화창 끔.
        
        CentralHub.Instance.NonINteractiveExecuter.InNonInteractiveMode = false; //논인터랙티브모드를 끝낸다.
    }

  위와 같이 조치했다.

 

  그리고 돌려보았다.

 

(대사 중간의 낙서 부분엔 내 이름이 들어가있당 =_=;;;)
(역시 낙서된 부분에는 내 이름이 있다..=_=)

 

우왕ㅋ굿 존나잘됑!!!!!

(옛날 유행어 뎨둉...)

 

 

  구라 안 치고 진구지 사부로 OST따라 3분 넘게 막춤췄음.

 

  늘 맘고생시키는 문제는 실상 별것 아닌 해결책으로 존나 간단히 해결되는 경우가 많은 것 같다.

  혹 지나가던 코딩고수분들이 비웃고 지나가실지 모르겠지만,

  코딩초보는 이런 순간이 정말 신난당.

  사실 근래 내가 하는 모든 작업을 통틀어 코딩이 주는 성취감이 제일 큰 거 같음.

  ...다만 별거 아닌 문제에 막혀서 날려먹는 시간이 너무 많아서 그렇지...ㅠㅠ

 

 

  아무튼 이제 본격적으로 탐문모드 구현에 들어갈 수 있겠당 ㅎㅎ

 

 

(참고로 일단은 기본기능 코딩에 집중하고 있어서, 인터페이스 요소들은 전부 임시뗌방입니다.)