던전을 입장하면 캐릭터가 가장 낮은 등급의 히어로들이 웨이드마다 랜덤으로 스폰된다. 인 게임 매니저(인게임의 진행되는 상황을 알 고 있는 클래스)에서 스킵버튼을 누르거나 웨이브시간이 지나면 자동적으로 몬스터 생성과 히어로를 랜덤 생성한다. 그 스크립트에서 아래 In_CreateObj클래스(히어로,몬스터들을 직접적으로 생성하는 클래스)의 함수를 호출한다.
사실 NGUI로 캐릭터를 이동하는것이 그렇게 까다롭지 않아 보였다. 히어로자체를 NGUI스크립트인 버튼으로 만들어서 히어로를 클릭하면 저번에 만들었던 히어로 상태창을 업데이트 해주고 그리고 땅을 찍으면 해당하는 위치로 캐릭터를 움직이면 된다.
UGUI를할때는 마우스로 클릭 한 스크린좌표를 월드좌표로 변환해서 오브젝트를 클릭한 위치로 움직이도록 했다. 이번에도 이 방법으로 하려고 시도해봤다.
게임을 제작하기 전에 리소스를 찾아보다가 알맞는 2D리소스를 찾았는데 sprite가 아니었다.(2D가아님.2.5D?) 그래서 NGUI좌표에 움직이는게 난해 했다. 위치를 기본적인 NGUI로 만들어진 UI들은 위치가 표준화?되어 위치잡기가 쉽지만 이 캐릭터들은 위치가 저멀리 딴 세상?으로 위치해 있었다. 그래서 기본적인 sprite의 Depth가 쉽게 조절이 가능한 반면 캐릭터들은 조절하기 좀 까다로웠다.
그래서문제점 => 캐릭터를 클릭하고 원하는 위치를 클릭하면 갑자기 맵뒤로 사라지기도 하고 예측하지 못한 위치로 이동하는 경우가 발생했다.
해결방법 :캐릭터의 위치를 이리저리 움직여봤더니 z값을 음수가 되는 순간 카메라 제일 앞에 위치됐다.
일단 캐릭터가 화면에 사라지는것은 잡았고, 또 다른문제점 =>문제는 캐릭터가 이동은 잘 되는데 클릭이 잘안된다. 이것 역시도 캐릭터가 sprite가 아니라 ngui의 boxCollider로 인식을 하지 못했다. 방법은 캐릭터의 sprite를 넣었다. 처음에는 비어있는 이미지를 넣고 알파값을 0으로 만들어서 안보이도록 하려했으나, 자식 오브젝트로 들어가 있는 캐릭터의 공격범위를 보여주는 circle의 sprite도 알파값이 0으로 변경된다.
해결방법 : 캐릭터의 sprite를 그림자로 만들었다.
사실 그림자가없을때 살짝 떠 있는지 느낌이어서 조금 아쉬웠는데 덕분에 이 부분도 해결됐다.
그리고
문제점 =>클릭한 위치로 이동하는데 캐릭터가 약간 중구난방에 서 있는 느낌이 들었다.
해결방법 : 클릭한 좌표가 아닌 맵타일의 위치 값을 받아와서 이동하도록 처리
캐릭터 대칭이동 : 마지막으로 캐릭터가 클릭한 좌표(움직 일 좌표)와 지금 서 있는 좌표랑 x값을 비교하여 좌우 대칭 이동을 처리했다.
스프레드시트를 이용해 테이블을 가져오는것 까지 완료했다. 이제 데이터를 통해 게임씬에 적용시켜야한다.
2. 조합표 구성
첫 번째로 구현 한것이 조합표 (어떤 캐릭터와 캐릭터가 있어야 조합을 할 수 있는지를 유저에게 알려주기 위한 표이다.) 이 조합표는 인게임에서 던전에서 게임중에 언젠든지 클릭하면 볼 수 있다.
일단 캐릭터 등급은 기본적으로 생성되는 1성 캐릭터와 조합으로 만들 수 있는 2성과 3성으로 구성되어있다.
조합표이기 때문에 1성은 제외하고 2성과 3성으로 sprite를 구성
조합표(테이블 로드되기 전)
구성은 위 이미지처럼 이렇게 되고 당연히 조합리스트들이 한 배경에 담지 못하기 때문에 UI Panel(Sofr Clip), UI Scroll View를 통해 드래그하여 다음 리스트들을 볼 수 있도록 처리했다. 테이블이 로드되고 캐릭터의 해당하는 조합구성이 넣어지도록 했다.
캐릭터sprite이름을Herotable nID값을 통일하여 해당 데이터의 맞게 고유값으로 처리했기 때문에 이미지 이름을 또 찾을 필요가 없다.
enum eHero
-실제 테이블 데이터와 비교
Comb Table데이터 로드된 조합표
또 2성은 3번째 조합재료가 없다. 그렇기 때문에 데이터값이 0이되면 오브젝트를 비활성화 하도록 처리했다.
문자열 배열을 받아서 위에서 부터 차례대로 받는다고 생각하고, 입력된 문자열중에 같은 문자열이 있으면 문자열 끝에 '(1)'을 추가해준다. ex) a라는 문자열이 존재한 상태에서 a를 추가하면 새로 추가한 문자열은 a(1)이된다. 그 다음 다시 a를 넣으면 a가 있기 때문에 a(1)으로 바꿔준다. 그런데 또 a(1)이 있기 때문에 a(2)로 바꿔준다.
가장 이해하기 좋은 테스트 문제
풀이 : 내가 작성한 코드
배열을 통째로 받지만 함수안에서 위에서부터 처음부터 받는다고 생각해야한다. 일단 문자열을 관리 할 수있는 컨테이너를 만든 뒤, 문자열을 하나 추가하면 그 컨테이너에서 새로 추가한 문자열이 중복이 있는지 체크한다. 그런데 여기서 한번 더 생각해야 할 것이 처삽입될 문자열을 바꾸고, 또 다시 컨테이너를 탐색해야한다. 컨테이너의 같은 문자열이 있을 수는 없기 떄문이다. for문으로 체크하기에는 배열의 인덱스와 요소 체크하기가 까다로울 것 같고,while문으로 삽입된 리스트들을 통째로 탐색하도록 한다.
count를 통해 같은 문자열의 갯수를 체크하고 문자열의 값을 변경하면서 while문을 통해 list를 탐색한다.
풀이 : 다른 사람이 작성한 코드
while(!set.Add(cade))를 통해 중복된 문자가있으면 카운트를 증가시키고 그렇지 않으면 set에 추가 하게된다. HashSet은 잘 사용하지 않았었는데 HashSet.Add에는 bool반환형이 있다. 추가되었으면 ture, 요소가 이미 있으면 false를 리턴한다.
','를 구분한 문자열중 가장 긴 문자열을 구하는 문제이다. 특수문자 제외, 쉼표(',')제외
풀이 : 내가 작성한 코드
빈 문자열 변수를 만들어 놓고 a~z || A <Z 사이에 포함되는 문자들만 입력한다. else는 ','를 받게되면 다음 문자열의 길이를 비교하여 다음 문자열을 만들 준비를 한다. 고려할 부분은 띄어쓰기와 특수문자를 제외하는 방법 이 두가지 정도가 있을 수 있다. C#문법만 하더라도 여러가지 방법이 있겠지만 나는 문자의 범위를 비교하였다.
풀이 : 다른 사람이 작성한 코드
Regex.Matches 문법을 사용했다. 입력 문자열에 있는 정규식을 모두 검색하고 일치 항목을 모두 반환한다고 한다. 그러면 자동적으로 띄어쓰기와 , 특수문자를 제외 시킨 문자가 m 입력된다. C#에는 다양한 문법이 있지만 게임에서 적용은 하기 힘들듯하다.
단순히 문자열을 for문을 통해 char요소를 하나씩 체크하여 숫자가 나오면 새로 생성한 int형 변수에 차근차근 더하여 계산 하려했지만, 숫자가 붙어있는 경우(즉 1자리를 넘는 경우)에도 모두 1의자리로 계산이된다. 그러면 숫자를 그때마다 int형으로 바꿔서 더하지 말고 십의자리 그 이상의 자리까지를 대비가 필요하다.char형 문자를 체크하면서 숫자가 나오면 string변 수에 넣어준다. 다음 문자가 숫자가 아닐때 까지, 숫자가 아닐 때 까지 모두 더한 string변수를 int형으로 변경하여 값을 더 해준다.
두번째 if문에서 temp !=""를 체크하는 이유 : 첫 번째 if문은 숫자가 아닐 경우 temp에 있는 값을 sum 변수에 더해주고 있다. 문자열 마지막요소의 형식이 숫자라면 그 전까지 더한 temp를 넘기게된다. 그래서 마지막 체크를 한번 더 해줬다.
풀이 : 다른 사람이 작성한 코드
foreach(Match match in Regex.Matches(inputString, "[0-9]+") 지정한 정규식을 통해 stirng 숫자값만 딱 뽑아진다.
우선 충돌처리를 하기 위해 boxcollider2D와 rigidbody2D컴포넌트를 추가했다.
이상하게 계속 검출이 안됐다. 이유는 rigidbody2D의 Simulated체크를 안했었다.
유니티도큐 : 리지드바디 2D 및 연결된 모든 콜라이더 2D와 조인트 2D가 런타임에 물리 시뮬레이션과 상호작용하도록 하려면Simulated를 활성화합니다(체크박스를 선택합니다). 비활성화되면(체크박스가 선택 해제되면) 이들 컴포넌트가 시뮬레이션과 상호작용하지 않습니다.
느낀 점 : 충돌처리를 할때는 생각해야 할 부분들이 있다 . Coliider,Rigidbody, 스크립트 상의 OnTrigger,On ColiiderOnCollisi
onEnter등 차이점과 활성화와 비활성화 했을때 각각 다른점들을 다시 한번에 체크해봐야겠다.
저 리스트 드랍다운버튼을 클릭하면 실행되는 코드 dataget이라는 data를 가지고 있는 클래스를 받는다( Define클래스를 통해 가져옴) 그런 뒤 listBox1.Item을 채워주면 밑에 목록들이 노출된다. 클릭할 때마다 해당하는 목록이 출력해주기 위해 클릭하는 목록들을 각각 0부터~인덱스를 매겼다.
두 번째 클릭
문제는 각 항목들을 처음 클릭 했을때 잘 노출이 되는데 전에 눌렀던 항목을 다시 클릭하면 리스트가 출력되지 않았다. 이유를 찾아보니 list.Clear()를 하면 생성자를 통해 static으로 새로운 객체를 만들어주고 있기 때문에, Define클래스에 가져오려던 리스트가 Clear가 되는 상황이다. 그리고 항목을 매번 클릭할 때마다 Define에서 받아 오는 것은 좋지 않다.
해결방법 :
프로그램 시작 시 한번실행되는 함수
처음 시작되는 함수에서 항목들의 데이터를 갖고있는 클래스를 리스트로 받고
항목을 선택 할때 리스트를 접근하여 해당하는 데이터 클래스를 불러오도록 수정했다.
느낀 점 : 정적클래스와 정적 데이터의 관하여 자주 실수하는 부분이 있기 때문에 개념을 확실히 잡고 메모리 관리에도 신경 쓰면서 작업을 해야겠다.