Game Development, 게임개발/배경지식

튜토리얼에 대한 고찰

게임이 더 좋아 2022. 3. 12. 14:50
반응형
728x170

 

오늘은 튜토리얼에 대해서 고찰해보려고 한다.

 

튜토리얼이란 무엇일까?

 

짧게 말하면 유저에게 프로그래머의 의도를 전달하는 것과 같다.

프로그래머가 유저에게 바라는 것을 게임 속에 녹이거나 전달하는 것이다.

 

맨날 메이플 얘기를 해서 미안하지는 않다.

그냥 내 첫 RPG라서 기억에 남는다.

 

 

튜토리얼을 보면 사용자의 행동을 유도한다.

 

1. NPC를 더블클릭을 유도하여 대화를 이끌어내고

2. Alt 버튼을 명시하여 사용자에게 조작법을 알려준다.

 

하지만.. 유도란 것은 유저가 알아채고 하기 싫어서 안하면 그만이다.

하지만 그렇게 되면 유저에게 프로그래머의 의도를 전달할 수 없다.

때문에 사용자의 예외 상황을 모두 고려해야 한다.

 

1. 만약 NPC에게 말을 걸지 않고 다음 맵으로 넘어가려하면 어떻게 해야할까?

-> 포탈의 활성화를 막는다.

 

2. 플레이어가 낙사데미지로 해당 맵에서 죽는다면 어떻게 해야할까?

-> 낙사데미지를 받는 높이의 지형을 없앤다.

 

3. 플레이어가 여기서 게임을 종료하거나 모종의 이유로 게임이 종료된다면 어떻게 해야할까?

-> 진행상황을 저장해왔던 것을 다시 불러온다.

 

4. 플레이어가 여기서 캐시템을 구입해서.. 장비창을 열어서.. 등등 튜토리얼에서 아직 배우지도 않은 기능들을 활용한 버그가 있다면 어떻게 될까?

-> 튜토리얼 중에는 예외상황이 많으므로 튜토리얼에서 필요한 기능을 제외하고는 비활성화한다.

 

등등 많은 것을 고려해야 한다.

 

그렇다. 이 많은 것을 누가 프로그래밍 해야하느냐??

나다. 클라이언트 개발자가 한다.

 


 

음... 유니티에선 저런 기능을 어떻게 할 수 있을까??

 

내가 튜토리얼에서 구현한 기능은 별로 안되지만 강력하다.

 

1. 튜토리얼의 진행 정도를 저장

 

2. 튜토리얼에서 사용자가 다른 기능은 사용하지 못하도록 잠금

 

3. 사용자가 유도대로 행했는지 확인할 수 있는 기능

 

크게 3가지를 구현했다.

 

즉, 유저는 내가 잠금해놓은 기능으로 인해 오직 내가 풀어놓은 기능만 사용할 수 있으며

해당 기능을 사용했는지 여부는 따로 판단해야하고

중간에 종료가 되었더라도 진행이 저장되어 다시 튜토리얼을 진행하는데 문제가 없다.

 

그렇다면 어떻게 구현했느냐? 이다.


 

먼저 튜토리얼의 진행정도를 저장하기 위해

플레이어의 현재 상태를 표현할 수 있어야 한다.

 

나는 이것을 Enum으로 저장하여 유저가 진행하고 있는 튜토리얼이 무엇인지 저장한다.

현재 상태가 first였고 종료되었다 다시 켜도 first이다. 그렇다면 first를 수행해야만 한다.

 

다음은 기능 잠금이다.

 

실제로 기능을 사용하기 위해선 전역변수나 정적 변수가 쓰이기도 하는데.. 튜토리얼만을 위해서 만드는 것이 정말 낭비아니냐?라고 할 수 있지만.. 튜토리얼은 완벽한 예외상황이라.. 우선 썼다.

사용자 입력 또는 UI와의 상호작용을 막는 것이다. 

flag로 막을 수도 있고 UI 위에 이미지나 패널 등을 놓아서  raycastTarget와 같은 것들로 기능에 대한 활성화를 막을 수 있다.

 

그리고 현재 플레이어가 행동대로 했는지에 대한 것을 ..어떻게 조사하느냐..?

 

 

이 미친놈은 장난쳐볼까라고 하지만 체력을 깎아버린다.

그냥 메이플의 가장 사이코패스가 아닌가 싶다. NPC가 때려진다면 가장 먼저 맞아죽었을 놈이다.

아무튼 로저가 아이템 소비를 유도하는데.. 사실 HP는 가만히 있으면 찬다.

그렇다면..아이템을 꼭 쓰지 않아도 피가 채워진다.

 

그래서 로저의 사과가 옛날에 무슨 희귀템이라면서 거래가 되었던 것 같다.

**옛날엔.. 교환불가라는 것이 없었던 시절이다.

 

하지만 현재는 아마 안 될 것이다.

 

아.. 그럼 2가지가 있다.

HP가 찬 것을 어떻게 아는거지...?

사과를 먹었는지 어떻게 아는거지...?

 

이 퀘스트는 HP를 채우는 것만 요구하기 때문에 사과를 먹었는지를 체크 안해도 되었다.

하지만 공부니까 예측해보면

 

인벤토리 시스템이 있다면

GetItemFromInventory(string id)라는 것이 분명 있을 것이다.

해당 로저의 사과에 해당하는 아이템이 없다면, null을 반환한다면...? 로저의 사과를 사용했다고 볼 수 있다.

 

**다만 버렸다면...? HP는 그대로인데..? (예외)

 

위와 같이 예외상황도 고려해야하므로 HP를 체크도 해야 한다.

 

여기서 또 문제!! 그럼 계속 GetItemFromInventory를 실행해서

계속 아이템 사용 여부를 체크해야하느냐...?

 

그렇다면 너무 자원낭비 아니냐..?

그렇다. 

 

그렇다면.. 언제 Inventory를 확인해야 하느냐..? 그건 프로그래머에 따라 다르겠지만..

플레이어가 소모품을 쓸 때 저 함수를 실행할 것 같다.

소모품을 사용한다면 사과를 먹을지 뭘 먹을지는 알 수 없지만

사과를 먹었는지는 확인해볼 수 있으니까 그렇다.

 

그렇다면 HP는 언제 체크해야하느냐..?

HP는 상관없다. 레벨 1이라고 친다면 최대 HP 50이라고 했을 때

50이상의 HP는 가질 수 없다. 

그렇다면 가만히 있어서 실행되는 함수인 hp회복 함수가 실행이 되면 안된다.

그렇다면.. hp 회복함수가 실행이 안되는 상황이 된다면 그게 체력이 만땅인 상태가 아닐까..?

뭐 그런식으로 할 수도 있다는 것이지

무조건 그렇게 해야한다는 아니다.

 

 


 

아무튼 요약해보자면

튜토리얼은

사용자의 예외상황을 고려해야 하며,

사용자의 입력 또는 상호작용을 조정해야하고,

사용자의 행동 여부를 알 수 있어야 한다는 말이다.

 

나는 여기서 Stencil과 UI image, panel, enum UniTaskVoid, 등등.. 여러가지를 조합해서 사용했다.

반응형
그리드형