히어로들이 공격할 때 와 몬스터가 죽을때 효과를 넣었다.

-몬스터가 피격 당했을 때

1. 머테리얼값 조정, 2. 체력 40%이하 체력바 초록색 -> 빨간색

- 몬스터가 죽었을 때

몬스터의 soul 값을 출력해주고, 파티클을 실행한다. (죽음과 동시에 InGameMng -> soul값 갱신

몬스터는 풀링으로 돌아가기 때문에 파티클과 soul표시 애니메이션도 같이 풀링스크립트에서 죽었다고 판단되는 몬스터의 위치에서 실행한다. 

-히어로 이팩트

궁수
마법사

원거리 공격 히어로들 각각 특징의 맞는 파티클을 넣줬다. 궁수는 방향계산으로 적의 위치를 계산해서 화살의 방향을 바꿔준다.

- 스테이지(던전 선택) 씬

팝업오브젝트는 한개로 공유하고 선택하는 내용과 제목을 변경하도록 설정했다.

 

 

 

-추가적으로 맵을 타일을 던전 진입 시 생성하는데 몬스터의 경로를 그려줬다. 그리고 나머지는 타일 이미지는 랜덤으로 배열된다. 

5. 히어로 랜덤생성

던전을 입장하면 캐릭터가 가장 낮은 등급의 히어로들이 웨이드마다 랜덤으로 스폰된다.  인 게임 매니저(인게임의 진행되는 상황을 알 고 있는 클래스)에서 스킵버튼을 누르거나 웨이브시간이 지나면 자동적으로 몬스터 생성과 히어로를 랜덤 생성한다. 그 스크립트에서 아래 In_CreateObj클래스(히어로,몬스터들을 직접적으로 생성하는 클래스)의 함수를 호출한다.

대충 진행되는 구조 순서는 이렇게 된다.

1. 웨이브스킵 or 웨이브 시간 히어로 생성 호출(히어로 몇명 만들 건 지)

2. ExtensionMethodw.class의 접근해서 스폰할 히어로의 랜덤 값(랜덤스폰이기 때문 / 히어로의 넘버)

3. 실제 생성 캐릭터가 자식으로 들어갈 부모위치

4. 던전 중앙에서 스폰되니 다시 한번 위치를 잡아준다. (정해 놓은 위치4가지 중 랜덤으로)

5. 인 게임의 히어로가 추가 되었음을 알리기 위해 히어로 딕셔너리의 추가해준다. 

 

In_CreateObj.class

이 메서드를 호출 할때 일단 몇명의 히어로들을 생성할 것인가, 그리고 웨이브마다 어떤 특정 이벤트를 넣을 것인가(나중의 특정 상황이 주어질 수 도 있으니 일단 넣어놨다)

히어로 생성할때 그 넘버값도 같이 보내는 이유는 히어로의 생성과 동시에 오브젝트의 이름을 같이 변경해 주기 위함이다.

네 번째순서의 히어로 위치를 정할 때 코루틴으로 사용한 이유는 캐릭터가 생성될때 이펙트의 진행과 동시에 캐릭터가 생성되는 느낌을 주기 위해 약간의 딜레이를 주었다. 

Define.class
히어로의 생성위치 4개를vector배열로 가지고 있음(랜덤 위치)

 

-현재까지 진행상황

4. 인게임_히어로이동 처리

사실 NGUI로 캐릭터를 이동하는것이 그렇게 까다롭지 않아 보였다. 히어로자체를 NGUI스크립트인 버튼으로 만들어서 히어로를 클릭하면 저번에 만들었던 히어로 상태창을 업데이트 해주고 그리고 땅을 찍으면 해당하는 위치로 캐릭터를 움직이면 된다.

UGUI를할때는 마우스로 클릭 한 스크린좌표를 월드좌표로 변환해서 오브젝트를 클릭한 위치로 움직이도록 했다. 이번에도 이 방법으로 하려고 시도해봤다.

게임을 제작하기 전에 리소스를 찾아보다가 알맞는 2D리소스를 찾았는데 sprite가 아니었다.(2D가아님.2.5D?) 그래서 NGUI좌표에 움직이는게 난해 했다. 위치를 기본적인 NGUI로 만들어진 UI들은 위치가 표준화?되어 위치잡기가 쉽지만 이 캐릭터들은 위치가 저멀리 딴 세상?으로 위치해 있었다. 그래서 기본적인 sprite의 Depth가 쉽게 조절이 가능한 반면 캐릭터들은 조절하기 좀 까다로웠다. 

그래서 문제점 =>  캐릭터를 클릭하고 원하는 위치를 클릭하면 갑자기 맵뒤로 사라지기도 하고 예측하지 못한 위치로 이동하는 경우가 발생했다. 

해결방법 : 캐릭터의 위치를 이리저리 움직여봤더니 z값을 음수가 되는 순간 카메라 제일 앞에 위치됐다. 

 

일단 캐릭터가 화면에 사라지는것은 잡았고, 또 다른  문제점 =>  문제는  캐릭터가 이동은 잘 되는데 클릭이 잘안된다.  이것 역시도 캐릭터가 sprite가 아니라 ngui의 boxCollider로 인식을 하지 못했다.  방법은 캐릭터의 sprite를 넣었다. 처음에는 비어있는 이미지를 넣고 알파값을 0으로 만들어서 안보이도록 하려했으나,  자식 오브젝트로 들어가 있는 캐릭터의 공격범위를 보여주는 circle의  sprite도 알파값이 0으로 변경된다.

해결방법 : 캐릭터의 sprite를 그림자로 만들었다. 

 

사실 그림자가없을때 살짝 떠 있는지 느낌이어서 조금 아쉬웠는데 덕분에 이 부분도 해결됐다.

그리고  

문제점 =>  클릭한 위치로 이동하는데 캐릭터가 약간 중구난방에 서 있는 느낌이 들었다.  

해결방법 : 클릭한 좌표가 아닌 맵타일의 위치 값을 받아와서 이동하도록 처리 

캐릭터 대칭이동 : 마지막으로 캐릭터가 클릭한 좌표(움직 일 좌표)와 지금 서 있는 좌표랑 x값을 비교하여 좌우 대칭 이동을 처리했다.

ExtensionMethod.class

 

- 현재까지 진행상황

3_인 게임 캐릭터 상태 업데이트

게임자체가 공격하는 유닛이 움직일 수가 있다. 그렇기 때문에 플레이어가 클릭한 캐릭터에 대한 정보를 표시해줄 필요가 있다.

여러 종류의 캐릭터가 있기 때문에 각 캐릭터가 생성될 때 데이터를 입력받도록 했다.

캐릭터에 정보를 가지고 있는 스크립트

- 캐릭터 사정거리(공격범위)

클릭하면 캐릭터의 공격범위를 표시되도록 했다.

- 지금까지 진행상황

각 캐릭터에 대한 정보 업데이트

각 히어로는 테이블을 통해 받아오는 데이터(이름,타입,공격력,공격범위,공격속도 등등)와 스테이지 진행상황의 데이터(레벨,그룹지정)등을 나뉘어진다.

 

스프레드시트를 이용해 테이블을 가져오는것 까지 완료했다. 이제 데이터를 통해 게임씬에 적용시켜야한다. 

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이되면 오브젝트를 비활성화 하도록 처리했다.

 

-현재까지 진행상황

 

 

NGUI 2D 조합디펜스게임 

예상 개발기간 : 3주~4주

게임소개 :  랜덤으로 생성되는 캐릭터를 조합(강화)하는 디펜스게임

 

1. 테이블구성

해당 타입의 맞게 스프레드시트를 통해 데이터를 불러와 표시하려고 한다.

config : 버전 등

stage : 스테이지 데이터들을 가지고 있는 테이블

Hero : 캐릭터 능력치

캐릭터 테이블

Comb: 조합테이블

조합표 테이블

캐릭터들은 nID를 통해 관리하고 싶어 hero,comb 테이블 각각 다르지만 ID를 고유값으로 설정했다.

사실 이렇게 초기셋팅은 해놨지만 구현하다가 바뀔수도 있을것 같다.

파일은 스프레드시트의 키값과 주소를 문자열을 파싱해여 Json형식으로 받아 데이터형식으로 받는다.

이 테이블은 각각 Table.class를 생성했고, TableMng.class를 통해 테이블을 요청했을때 해당하는 테이블 데이터를 리턴하도록 만들었다. 

그리고 게임시작할때 한번 모든 테이블과 데이터들은 로드된다. 이 테이블이 다운로드되는 시간을 로딩신으로 구현할것이다. 

게임시작 시 실행

 

-형상관리툴

소프트웨어 버전 관리 툴이라고 생각하면 될듯하다. 

-형상관리는 소스의 변화를 끊임없이 관리하는 것이다. 개발과정에서 소스를 수정하거나 특정 시점으로 되돌릴 수 있기 때문에 특히 협업프로젝트는 필히

형상관리 툴로 깃허브,빗버킷,깃랩,SVN등이 있지만 이 프로젝트는 깃랩을 사용하기로 했다.

이유는 pravite저장소에 10GB용량을 무료로 지원해주기 때문이다.

-소스트리

사실 깃을 사용하기에는 쉽지않다. 깃에서 사용되는 명령어들도 알고 있어야한다.  그래서 좀 더 쉽게 사용하기 위해 소스트리 https://www.sourcetreeapp.com/ 를 이용하기로 했다.

소스트리

연동방법:  Clone탭 -> 첫 번째칸에는 깃랩 프로젝트의 주소를 넣고 두 번째 경로에는 내 로컬저장소 위치를 넣어주면된다.

유니티는 Asset,Packages,ProjectSettings 이 3개의 폴더만 푸쉬해야한다.

그렇기 때문에 이런식으로 무시 해두자. 한번 무시하면 저폴더의 하위목록들은 커밋창에 뜨지 않는다.

소스트리는 커밋으로 로컬 저장소에 올린 뒤에 푸쉬를해서 서버에 올리는 방식이다. 이중저장같은 느낌

 

유의점

- 작업하는 유니티버전 맞추기(버전마다 리소스의 메타파일 ID가 다를 수 있음)

- Edit - Project Settings - Asset Serializationg - Force Text로 변경

씬에 변경된 내용을 추적이 가능하다고 한다. 아직 해본적이 없지만 일단 이렇게 셋팅!

그래프 알고리즘 중에 깊이 우선 탐색(DFS) 과정을 유니티로 구현해봤다.

깊이 우선 탐색은 먼저 해당하는 모든 정점을 탐색하고, 넓게(wide) 탐색하기 전에 깊게(deep) 탐색하는 것이다. 인접 노드를 먼저 탐색하고 인접 노드를 모두 방문하면 그다음 정점으로 탐색한다.

 

알파벳 박스들은 정점, 보라 색선은 간선이다.  Clear 버튼을 누르면 데이터를 가지고 있는 컨테이너들을 비워주고 위치 또한 다시 랜덤으로 설정하도록 했다.

오른쪽에 긴 사각형이 stack으로 실제 정점데이터가 stack으로 push 또는 pop 되면, 정점에 해당하는 이미지박스 역시 채워지고 비워진다.

노란색으로 바뀌는 박스는 stack에 들어있는 정점이고, 파란색은 방문한 정점이다. (방문한 정점은 다시 방문하지 않음)

트리 알고리즘을 공부하다 보니까 

공부한것을 이용해 보고싶다는 생각이 들었다.

그래서 유니티로 트리구조를 가시적으로 보이도록 구현해봤다.

이진트리와 AVL 트리를 구현했다.

 

둘다 기본적인 구조는 이진트리이다.

삽입된 노드는 root노드부터 비교하면서 자신의 값보다 현재

위치한 노드가 크면 왼쪽 삽입된 노드가 크면 오른쪽으로 이동한다. 

바이너리(이진)트리

 

이진트리. 삽입/ 찾기

 

 

 AVL 트리

트리의 균형도가 절대 값1이 넘어 갈 경우 자동으로 균형 회전을 하도록 구현했다.

avl트리 LL회전

 

AVL트리 RR회전

콘솔로만 구현하기는 인터넷에도 많고 구현도 잘되어 있다.  트리구조에 따라 UI오브젝트도 움직이는 이려면 추가적으로 자료구조 구현이 필요하다.

사실 실제 데이터가 움직이는 트리구조와 이미지박스가 움직이는 것은 아예 상관이 없이 움직인다고 생각하면 된다. 별도로 움직여야 한다.

 

내가 구현한 코드에 노드는 Key는 int비교를 하기 위한 변수로 사용하고

Value는 오브젝트를 움직이기 위한 변수를 같이 담고 있다. (키 값을 통해 오브젝트를 불러오기 위함)

먼저 오브젝트의 위치를 움직여주고 그 다음에  트리구조에 데이터 구조를 변경하도록 한다.

 

점프구현하기

<현재>

 

(수정 전)

(수정 후)

 

 

위 그림처럼 캐릭터가 타겟을 노란색 테두리를 착지 지점으로 계산하여 점프하는 구현하였다.

캐릭터가 중앙지점을 가장 높은 위치를 지난 후 밑으로 떨어질 때 속도가 빨라져야 더 자연스러운 점프모션이 될 것같다. 

 

 

점프기능은 여러가지 방법이 있겠지만 DoTween을 사용했다.

스크립트를 살펴보자

Transform stpos; //플레이어 위치

Transform endpos; // 스킬발동 위치

Rigidbody Prb; //플레이어 Rigidbody

public void Jumpping()

{

Vector3 hpos = stpos.position + ((endpos.position - stpos.position) / 2);

 

Vector3[] Jumppath ={new Vector3(stpos.position.x,stpos.position.y,stpos.position.z),

new Vector3(hpos.x,hpos.y+3f,hpos.z),

new Vector3(endpos.position.x,endpos.position.y,endpos.position.z) };

Prb.DOPath(Jumppath, 2, PathType.CatmullRom, PathMode.Full3D); //점프구간

 

}

중간백터

Vector3 hpos = stpos.position + ((endpos.position - stpos.position) / 2);

hpos는 캐릭터에 움직일 path경로중 시작백터와 종료백터의 중간 백터가 된다.

 

path경로 설정

Vector3[] Jumppath ={new Vector3(stpos.position.x,stpos.position.y,stpos.position.z),

 new Vector3(hpos.x,hpos.y+3f,hpos.z),

 new Vector3(endpos.position.x,endpos.position.y,endpos.position.z) };

캐릭터가 지나갈 경로를 배열로 받는다. 시작백터그리고, 중간백터, 끝백터를 차례로 넣어준다. 

여기서 중간백터의 y값은 캐릭터가 얼마만큼 점프할 것인가를 +해주면 된다.

 

점프동작부분

Prb.DOPath(Jumppath, 2, PathType.CatmullRom, PathMode.Full3D);

마지막으로 실제 점프가 이루어지는 DOpath인데 Dotween은 캐릭터의 리지드바디로 움직일 캐릭터를 설정해주고, 계산한 점프경로 백터 배열, path이동 타입을 설정해준다. 

 

여기서 추가 업그레이드 해야 할 부분은 거리에 따른 점프시간(공중에 떠 있는 시간) 플레이어의 위치에서 점프하려는 거리에 맞게 점프시간을 설정하도록 할 것이다.  

 

 

 

 

스테미너 효과 UI 



내가 제작하고 있는 게임은 공격액션을 한번 취할때마다 한칸의 스테미너를 소모한다 

위 그림에서 알수 있듯이 연속적으로 3번 사용가능하고 시간이 지나면 다시 공격을 할 수 있도록 스테미너가 채워진다.

삼 등분으로 나누어 회색게이지가 한 칸찰 때마다 주황색 게이지가 채워지는 형태로 스테미너 HudBar를 구현했다.


필요한 이미지

이미지는 총4개 

1) 아무것도 채워지지 않은 상태를 표시하기 위한 배경

2) 점점채워지는 회색게이지바

3) 한칸씩 채워질 주황색 게이지바

4) 명확한 표시를 위한 3칸 나눔선


회색 게이지바는 시간초로 계산하여 매초마다 계속해서 증가시켜주고 

주황색게이지바는 2초의 한 1칸씩 6초후에 3칸이 된다. (maxguage는 6초)

이미지 위치를 다르게 놓고 보면 좀 더 명확하게 볼 수 있다.

스테미너 부족 시 떨림 효과




현재 제작하고 있는 게임은 스테미너가 없으면 공격을 못하는 방식이다. 그런 방식때문에 스테미너 부족상태를 명확하게 전달 할 필요가 있다즉 공격불가라는 표현을 텍스트대신 스테미너Bar가  좌우로 흔들리고 빨간색으로 변하도록 표현했다.


좌우 떨림효과

여러가지 표현방법이 있게지만 나는 DOTween을 이용했다.

DOTween을 이용하여 스테미너Bar가 전체를 좌우로 흔들리 도록 해주었다.


빨간색 알파 효과 

기존이미지의 색상을 빨간색으로 바꾸는것보단 미리 빨간색 이미지를 같은 사이즈로 만들어 놓는다.

알파 값을 0으로 놓고 평사시에는 안보이도록 숨겨놓는다. 


그리고 스테미너 부족상황이 오면 이 이미지의 알파값을 DOFade로 조절한다. 

+ Recent posts