UI만 NGUI에서 UGUI로 고치면 되는데 왜 문제가 생기느냐...라고 생각했는데, 점검해보니 이전부터 있었던 문제를 내가 미처 알지 못했을 뿐이었던 것 같다.
장소이동 메뉴는 위와 같이 되어있다. 이미지들은 임시용이거나 예전에 만든 비주얼노벨 이미지 재활용인데, 오른쪽 위의 인물을 여기서 쓰는 건 엄밀히 말해 무단도용-_-;;; 이기 때문에, 출처를 밝혀둔다. 저 그림 그리신 분은 구름과자 작가님으로, 해당 그림은 나와 협업한 《슬픔을 나에게》에서 사용되었다.
저 장소이동 메뉴의 작동방식은 이렇다.
1.메뉴 가운데의 이미지는 이동하고자 하는 장소를 미리 보여주는 이미지다.
2.메뉴 내용 갱신하기 : 메뉴 좌 / 우의 화살표 버튼을 누르면 이동 가능한 장소를 이전/다음으로 넘긴다(가운데 장소 미리보기 이미지와 장소 이름, 장소 설명이 바뀜)
3.메뉴 좌하단 "이동한다"를 클릭하면 메뉴상에서 미리 보여지는 장소로 이동된다. "그만둔다"를 누르면 이동 메뉴를 끈다.
지금 문제가 되는 건 두 번째 부분인 "메뉴 내용 갱신하기"이다. 이동 가능한 장소는 장소정보class 배열로 기록되어있다. "이동하기"가 눌려지는 순간 현재 가리키고 있는 배열의 장소정보class에 담긴 장소명을 가져와
Instantiate(Resources.Load("Locations/" + 장소명).....
위와 같이 불러내는 방식이다. 그러니까 이전/이후 버튼을 누를 때마다 참조(이 용어가 맞나?)하고자 하는 배열 인덱스를 앞 뒤로 옮겨가게 되는 건데, 여기서 문제가 생긴다. 다음 규칙 때문이다.
-이전/다음 버튼이 눌렸을 때 가리킨 주소의 장소로 아직 이동할 수 없거나(장소 클래스의 bool변수로 관리되는데, 배열이 퍼블릭으로 선언되어있는 관계로 인스펙터에서 컨트롤 가능), 현재 플레이어가 위치한 장소인 경우 그 다음 인덱스에 접근한다.
-그 인덱스도 마찬가지 조건에 걸리면 또 다음 인덱스로 넘어간다. 조건이 클리어될 때 까지 반복.
-만약 첫 번째 인덱스/마지막 인덱스에 접근하는 상황에서 이전/다음 인덱스로 넘어가게 되면, 배열의 마지막/첫 번째 인덱스를 가리킬것. 단, 이 때에도 아직 이동할 수 없는 장소거나 현재 플레이어가 위치한 장소인 경우 이전/다음으로 넘어간다.
발생한 문제는 1.현 위치의 장소가 메뉴상에 표시됨. 2.아직 막혀있어야 할 장소가 메뉴에 나옴.
즉 총체적 난관이다...
거두절미하고, 끙끙거리며 원인을 알아보니 다음과 같은 문제가 있었다.
일단 기존에 사용한 처리 방식은, 버튼이 눌리면 접근하는 배열 인덱스 값을 --히거나 ++한 뒤, "현 위치인가? || 아직 이동 불가능한 장소인가?"를 if문으로 검사해서, 그렇다고 하면 조건에 맞는 인덱스가 나올 때 까지 while문으로 인덱스 값을 올리게 되어있다. 그런데 오작동이 난 이유는...
1.이동 가능한 장소가 "현 위치"딱 하나 밖에 없는 경우를 따로 처리하지 않았음 : 이동가능 장소 첫 번째에는 탐정사무소가 있다. 즉 이동 메뉴를 열면 탐정사무소부터 나온다. 내 생각에 탐정사무소는 항상 이동가능한 장소일 테니까, 메뉴를 열자마자 "여기가 이동 가능한 장소인가 아닌가?"를 체크할 필요는 없다. 하지만 이동 가능한 장소가 탐정사무소밖에 없는 경우(게임이 막 시작했을 때에는 탐정사무소 이외의 장소로는 갈 일이 없을 것이다)뿐만 아니라 이동 자체가 금지되어 있는 경우(강제 이벤트로 인하여 현재 장소를 이탈하면 안 되는 경우)도 있을 것이기 때문에, 이와 같은 조건에서는 이동 메뉴가 아예 열리지 않도록 처리하는 게 좋겠다.
2.처음에 버튼을 클릭한 후 if문으로 현 위치인지, 아직 이동이 불가능한 장소인지 여부를 검사하지만, while문에서는 이동 가능한 장소인지 여부만 검사하고 현 위치인지 여부는 검사를 안 함.
3.while문 도중 첫 페이지 이전으로 가는 경우/마지막 페이지를 넘어가는 경우를 따로 처리해두지 않음.
솔직히 말해 NGUI버전 당시 왜 문제가 없다고 생각했었는지 이해가 안 갈 정도이다.
아무튼 1번 문제는 "이동메뉴가 안 열리도록 처리하는 함수"를 만들어서 해결하기로 했다. 아마 이동 메뉴 대신 "지금은 이동할 상황이 아니다"같은 독백대사가 나오도록 하면 될 것 같다. 탐정사무소 이외에 이동할 장소가 없거나, 강제이벤트로 이동이 금지된 경우 이 함수를 호출하면 될 것이다.
2번 문제는, 생각해보니 처음에 if문으로 검사할 필요가 없다. 그냥 while문에서 "이동 가능한가?" "현 위치인가?"를 검사하면 그만이라는 걸 깨달았다. 3번 문제는 while문 안에 if문으로 첫/마지막 인덱스를 넘어가버렸는지 여부를 체크하면 될 거 같고.
그래서 아래와 같이 해봄.
//코드 안의 한글은 변수명이나 메서드를 실제 스크립트에서의 명칭이 아니라
//역할 설명용으로 적절히 고쳐놓은 것임
public void 이동메뉴열기()
{
if (이동메뉴OnOff) //장소이동 메뉴가 켜있다면(true)
{
이동메뉴오브젝트.gameObject.SetActive(false); //메뉴를 끈다.
destinationMenuOnOff = false;
//그리고 메뉴를 생성하면서 변경되었던 변수들을 재초기화 해야한다.
이동메뉴페이지번호 = 0; //페이지는 다시 첫페이지(0)를 가리키도록...
}
else
{
이동메뉴오브젝트.gameObject.SetActive(true); //반대의 경우 메뉴를 켠다.
액션메뉴이동메서드(); //액션목록 메뉴는 도로 넣는다.
이동메뉴OnOff = true;
//여기서 펼쳐지는 것은 꺼져있던 이동메뉴가 열릴 때의 과정이다.
//다음, 만약 이제 펼쳐질 페이지가 현재 장소와 같다면(=현위치가 사무실이라면) 다음 페이지가 펼쳐지도록 조치.
if (장소목록배열[이동메뉴페이지번호].장소이름문자열 == 현위치이름)
{
다음페이지로넘기기체크메서드(); //이 메서드가 실행되면
//이동 가능한 장소의 페이지번호에 도달할 때 까지 페이지번호가 계속 증가된다.
}
장소이동메뉴갱신메서드(); //결정된 페이지번호에 따라 장소이동 메뉴의 내용을
//갱신한다.
}
}
public void 이동메뉴다음페이지버튼메서드()
{
if (이동메뉴페이지번호 >= 장소목록배열.Length - 1)
{ //일단 버튼이 눌린 시점에 마지막페이지라면 다시 첫 페이지로 돌린다.
이동메뉴페이지번호 = 0; //첫페이지, 즉 사무실은 항상 해금되어있으므로 장소체크는 필요없다.
}
else 이동메뉴페이지번호++;
다음페이지로넘기기체크메서드();
장소이동메뉴갱신메서드();
}
void 다음페이지로넘기기체크메서드()
{
while (장소목록배열[이동메뉴페이지번호].해금여부 == false || 장소목록배열[이동메뉴페이지번호].장소명 == 현위치이름)
{//접근하려는 인덱스가 해금되지 않았거나 현위치인 한 계속해서...
이동메뉴페이지번호++; //하나 올림
if (이동메뉴페이지번호 >= 장소이동목록배열.Length - 1)
{ //그렇게 올라간 값이 막페이지를 넘기면 다시 처음으로 돌려놓음
이동메뉴페이지번호 = 0; //첫페이지, 즉 사무실은 항상 해금되어있으므로 별도의 처리가 필요없다.
}
}
}
public void 이동메뉴이전페이지버튼메서드()
{
if (이동메뉴페이지번호 == 0) //버튼이 눌린 시점에 페이지번호가 0이라면
{
이동메뉴페이지번호 = 장소목록배열.Length - 1; //목록의 마지막을 가리키도록함.
//마지막 페이지의 장소는 아직 해금되지 않았을수도 있으므로 반드시 췍해줘야 한다.
}
else 이동메뉴페이지번호--;
이전페이지로넘기기체크메서드();
장소이동갱신메서드();
void 이전페이지로넘기기체크메서드() //이 메서드는 다른 데서 쓸 일이 없을 듯 해 메서드 안 메서드로 처리
{
while (장소목록배열[이동메뉴페이지번호].해금여부 == false || 장소목록배열[이동메뉴페이지번호].장소명 == 현위치이름)
{
이동메뉴페이지번호--;
//그런데, 만약 현위치가 사무실(=첫 인덱스)이라면, 조건에 의해 while문이 실행되어 페이지번호가 0이하로 떨어지게 된다.
//이대로 가면 오류가 나므로..
if (이동메뉴페이지번호 <= 0)
{
이동메뉴페이지번호 = 장소목록배열.Length - 1; //목록의 마지막을 가리키도록함. ;
}
}
}
}
결론적으로 말하자면 다 해결했다.
문과뇌로 수고 많았다. 나를 칭찬해~
다만 코딩의 재미가 기능 하나하나 구현해낼 때의 "해냈다!"감성인데, 진도는 못 나가고 기존에 짠 코드나 쪼물딱하니 영 보람이 없다.
아직 "이동 가능한 곳이 사무실밖에 없는 경우"를 어떻게 판단할지 방법을 떠올리지 못했다. 그리고 이동불가 메서드도 안 만들었고.
'탐정게임 만들기 일지' 카테고리의 다른 글
[유니티]주먹구구 탐정게임 만들기 - 대화가 다 종료된 후 실행하기 (0) | 2020.03.10 |
---|---|
[유니티] 주먹구구 탐정게임 만들기 - 아이템 끌기 기능 만들기. (0) | 2020.01.17 |
[유니티] 주먹구구 탐정게임 만들기 - UGUI교체작업 (0) | 2019.12.31 |
[유니티] 주먹구구 탐정게임 만들기. 2019-12-16 (0) | 2019.12.16 |
[유니티] 주먹구구 탐정게임 만들기. 2019-12-09일 (0) | 2019.12.09 |