진짜 미친듯이 최선을 다한...까지는 아니였지만 (동생 실기로 인해 주말에 불참 ㅠ)
그래도 누가 아파서 통으로 빠지거나하지않고 처음
으로 모든 구성원이 열심히 시간 맥스로 채워서 달린 프로젝트 였던 것 같다.
이번에는 몬스터 전반 및 낮 과 밤 로직등을 맡아서 구현했다.
오브젝트 풀링이나 스폰매니저, CSVtoSO등은 내가 이전에 쓰던 코드를 가져다가 사용했다.
점점 프로젝트를 하다보니 다시 사용할 수 있는 코드들은 재사용하게 되니 1시간정도는....빨라진 것 같기도.
몬스터 구현은 강의의 FSM을 사용하여 구현하였다.
몬스터 상태가 몇가지 없어서 그냥 구현할까하다가 그래도 배운걸 적용해보고자 FSM을 사용하였다.
처음에 chase랑 Attack 만 존재하는 상태라 아 이걸 왜 복잡하게 이렇게 한다고 했지... 싶었지만 몬스터가 chase상태에서 죽을 때 계속 이동하며 애니메이션을 재생하는 문제가 있었다. 이때 그냥 플래그로 이동을 막을 수도 있었겠지만, state machine을 구현해놨으니..! die 상태를 추가해줘서 die 애니메이션을 실행하게하였다. 아주 편안하게 멈춰서 죽는걸 볼 수 있었다..!
die애니메이션후 disalbe상태로 만드는 것도 사실 die 상태에서 해주면 됬겠지만 처음에 애니메이션이벤트로 붙여놔서 그냥 냅두었다. 어쨌든 die상태를 추가하는게 매우 쉬워지는 것을 볼 수 있었다.
몬스터 스폰은 이전 숙련 주차에서 구현했던 areaspawner와 유사하게 일정 반지름 안에서 생성되도록 하려고 했다가 그래도 베이스 캠프의 일정 범위 밖에서 생성되어야 했기 때문에, min max radius를 받아서 position을 정해서 스폰하도록 했다. 그리고 코루틴으로 일정 시간 간격으로 지속적으로 스폰되도록 하였다.
팀원분이 난이도 ui를 만들어 주셨기에, 난이도에 대응할 수 있도록 spawndata를 만들고, 난이도별로 so를 만들어 난이도에 따라 데이터를 갈아끼워 몬스터 스폰양을 조절 할 수 있도록 했다. 이렇게 되니 난이도가 현재처럼 3개가 아니라 5개로 늘어나도 so와 enum, ui만 추가해주면 난이도 조절은 쉽게 할 수 있게 되었다.
난이도에 따라 몬스터의 스폰량이 늘어나는데, 이를 처음에는 그냥 선형적으로 늘어나게 하고 있었다.
그랬더니 몇일만지나도 엄청나게 불어있는 몬스터를 볼 수 있었다. 이로인해 렉까지 걸릴정도..
렉 뿐만아니라 난이도 면에서도 답이 없었기 때문에 log함수를 사용하여 몬스터의 증가량을 제어해주었다.
몬스터를 디스폰해주는 것은 이 스포너 스크립트가 베이스 캠프에 붙어있기는 하지만..! 몬스터를 이 스크립트가 달린 오브젝트의 자식으로 스폰해서 자식오브젝트를 싹다 for문돌며 setactivefalse해준다.
풀링은 자동으로 되고있다! 오브젝트를 스폰할때 SpawnManager로 스폰한다면 해당 오브젝트를 비활성화할때 자동으로 풀에 들어가게 뒤의 프레임워크를 구현해두었다. 단점이라면 GameObejct밖에 풀링을 못한다는 것... 다른 클래스들을 풀링하려면 사실 classpool이라는 다른...풀을 만들어두었지만 일단 이번엔 사용하지 않았다. 이건 다른 프로젝트에서 사용했었는데 이를 SpawnManager로는 스폰할수가 없다.. ㅠ 다르게 방법을 고민해봐야겠다.
난이도에 따라 몬스터 스폰양이 달라지는 건 좋은데.. 구매한 에셋이 몬스터가 한종류라 아쉬웠다. 그래도.. 우린 scale을 바꿀 수 있다. scale을 바꾸어 몬스터를 3종류로 만들었다. 그리고 팀원들 item을 so로 한땀한땀 관리하는걸 보니 엄청 귀찮아보였고... 나는 저런걸 참을 수 없다. 예전에 숙련주차 개인과제때 만들었던 csv to so를 활용해서 csv로부터 몬스터 데이터를 로드해서 몬스터의 데이터를 so로 관리하도록 만들었다.
이렇게 만들고나니 상위 몬스터의 등장 확률이 문제였는데. 이런 무한 스테이지에서 관리하는 방법이 있을까 하여 튜터님께 여쭤보러 갔더니 기획자의 영역이라 기획자마다 천차 만별이란다...! 뭔가 알고리즘 같은게 있지 않을까 했는데..! 근데 생각해보니 당연히 데이터를 관리하는 방법도 다를 것이고 몬스터의 종류 등등도 다를테니 그게 맞는 것 같기도하고.
그래서 일단 작은 게임이고 테이블을 하나더 만들고 그걸 핸들링 하도록 하려면 사실 그냥 게임 전체의 데이터를 갖고 있는 데이터를 만들고 해야할 것 같은데 거기까진 시간견적이 절대 안나오니.. 몬스터의 아이디를 0부터 시작하게 해서 지난 날짜를 최대 id값까지 모듈러 값을 취해서 0일때 그 아이디의 생성 확률이 1/(id개수*10)만큼 증가하도록...
즉, 지금까지 지난 날짜를 담은 변수가 day라고 할때,
if day%id ==0 then
if idspawncount[id]<=10 then
spawnweight[id*10+idspawncount[id]+1] = id
idspawncount[id]++
spawnweight는 저기서 random index를 뽑아서 들어있는 id의 몬스터를 생성하는 그런 array이고, idspawncount는 해당 id가 몇마리나오는지를 갖고있는 dictionary이다.
메모리 효율성이 좀 나쁠 수 있지만.. 빠르게 생각 할 수 있는 방법이었다.
그리고 낮과 밤의 변환은 그냥 간단하게 하루시간과 낮의 시간을 정해주면 코루틴을 돌며 낮 밤을 바꾸게 해놨다.
물론 event를 두고 타임이 바뀔때 실행되어야 하는 함수들을 구독받게 event도 열어놨다!
이에 대해서 사실 하루가 바뀔때 일어나야하는 event와 낮밤이 바뀔때 일어나는 이벤트 둘로 나누어 놨는데.
하루가 바뀔때, 낮이될때, 밤이 될때로 나누어야 했었을 것 같기도 하다. 이렇게되면 몬스터 스폰해주는 부분에서 스위치문을 써야하므로..
기획이야기할 때 밤에 베이스캠프에서 멀어지면 화면이 어두워지면서 정신력이 떨어지는.. 그런기능을 만들자고 이야기가 나왔었다. 그래서 정신력은 플레이어에서 해줘야하는데 플레이어를 갈아엎고 있으므로.. 거리에 따라 화면이 어두워지는 기능만 만들었다.
거리에 따라 시그모이드 함수를 따라 알파값을 조정하였다.
플레이어 화면에 비해 오브젝트가 생성되는 범위가 너무 넓었다. 그래서 미니맵이 있으면 좋겠다는 이야기가 나와서 만들었다. 사실 기술적으로 별거 없는데 팀원분들이 되게 신기해하셔서... 재밌었다.
RenderTexture를 생성하고, 이 생성한 랜더텍스쳐를 카메라의 TargetTexture에 할당해주었다. 물론 이 카메라는 플레이어가 메인으로 보는 카메라가 아니다! 미니맵에만 보여야할 정보들로 컬링 마스크를 설정해주고, 이 카메라도 플레이어를 따라가게 해준다음 해당 RenderTexture를 UI를 만들어서 RawImage컴포넌트를 만들고, Texture로 할당해주었다.
아이템도 구조가 잘못잡혀있어서... 간단하게 수정해두었는데 내가 처음부터 개발한건아니므로 패스.
'Develop_Log' 카테고리의 다른 글
[내배캠 최종 프로젝트] 맵 장애물 구현 (0) | 2024.12.03 |
---|---|
[ScriptableObject Loader] Excel에서 SO로 만들기 (0) | 2024.11.24 |
유닛 스텟에 빌더패턴 적용 (1) | 2024.10.25 |
[TrobleShooting] ww로 달리기 구현 (0) | 2024.10.24 |
유니티 입문 주차 회고 (2) | 2024.10.22 |