🕹️ GMTK Game Jam 2025
Farm Tracker
FarmBox Tracker
- 객체 별 update로 체크하는게 아니라 replaymanager에서 체크하려고 로직 다시 갈아엎었는데
- 두번째로 방문했을 때 기록이 알아서 정렬되는게 아니라서 플레이어별로 저장해놓는게 맞았음. 시간 낭비. 다행히 바로 깨달아서 ctrl + z로 많이 복구됨.
행동 저장 및 재생
- FarmBox에 식물 등장하고 사라지는 기록 : 재생할 때, 누가 심은 곳에 심거나, 물을 주거나, 심을 곳에 심어버리면 안됨.
- 문 통과하기 (이건 TrackPos로 가능)
- 시간문 통과하면 존재가 사라짐 (하루가 끝난 것과 같은 로직 돌리기)
침대에 자야 끝나는 걸로 변경하기
과거의 나와 닿으면 게임 오버
타임 패러독스 로직 구현
- 위험 행동 : 심기, 물 주기, 수확하기
- ghost가 수확하려 했는데 작물이 없음 (플레이어가 이미 수확해버림)
- ghost가 심으려고 했는데 이미 심어져 있음 (플레이어가 이미 심어버림)
- 물이 뿌려지지 않을 예정인 식물에 플레이어가 물을 줘버림
- '물이 뿌려지지 않을 예정인 식물'은 해당일 모든 plant의 watered를 확인한 뒤, watered = false라면 can_player_waters = false로 놓기
- 새로운 날이 시작되었더라도 그것이 이미 지나간 과거의 미래일 수 있기 때문에, watered paradox 정보는 update해야 함
- 만약 오늘이 끝났을 때의 정보가 없다면, can_player_waters = true
- DayPassed()같은 로직과는 별도로 정보를 관리할 것이므로, 어느 순서로 들어가도 상관은 없다.
- 하루가 시작할 땐 땅이 비어있는데 나중에 물을 줄 수 있으므로 can_player_water은 farmBox를 기준으로 해야됨.
버그
- 아직 과거의 내가 하지 않은 행동들이 다 끝나기 전에 하루를 끝내버리면 그 상태로 다음날이 되는 버그
- 하루가 끝날 때, 남아있는 행동들을 전부 재생한다
- posRecs도 재생을 해야 자고 있을 때 닿는 걸 확인할 수 있음.
- 과거의 행동은 패러독스가 일어나지 않는다. 하지만 시간 순서에 따라 패러독스로 오인될 수 있다.
- 각 ghost 별 시간대만 맞춰도 안된다. ghost A가 수확만 하고 심지 않았었는데, ghost B가 거기에 씨앗을 심었다면, ghost A가 수확을 하지 않았을 때 ghost B가 이미 있는 곳에 심으려다가 paradox를 일으킬 수 있다.
- 모든 ghost의 남아있는 Recs를 priority queue 한 곳에 모은 후에, 하나씩 빼면서 순서대로 명령을 실행한다.
- 가장 부하가 걸리는 것은 posRec. 0.5초에 한 번씩 tracking을 하므로, 가상 최대 인원 6명 최대 시간 210 2 (0.5초에 1번) * 2 (넣고 빼기). 거기에 우선순위 큐 삽입 삭제가 NLog(N)이라 가정하면 5천은 훌쩍 넘어갈수도...
- 코루틴으로 분산하면 된다고는 한다. 연산 중에 대기 텍스트를 띄워야 할듯.
- 생각해보니 posRec은 순서를 고려할 필요가 없다. 나머지 Rec만 해주면 됨. 그렇다고 하더라도 남아있는 posRec을 전부 1프레임에 연산하는 건 부하가 심함. 지금 당장은 버그 해결만 해두고, 코루틴으로 연산 나누는 건 뒤로 미루기.
- posRec을 직접 충돌 연산하는 대신 플레이어와의 거리로 대충 연산하면 최적화되긴 함.
- 그리고 우선순위 큐 말고 그냥 list에 다 모아놨다가 sort하면 끝임. 굳이 외부 라이브러리 같은거 생각 할 필요도 없다.
- 하지만
List<T>로 묶을 수가 없다. 각 Recs는 class가 아니라 struct이기 때문. 성능 생각 안 하고 class로 바꿔서 상속으로 하나로 묶는다고 하더라도 공통된 정보가 없어서 곤란.
- 코드랑 이거 그대로 긁어서 gemini한테 물어봤더니 놀랍게도 답을 해줬다. struct도 interface 상속이 가능하며, 그냥 if문 때려버리면 그만 아니냐고... posRec 제외하면 갯수많으니까 확실히 그렇다.
- 결론
- posRec : 순서 상관 없이 플레이어와의 거리 연산
- 나머지 Rec : 각 struct에 interface 할당, List에 다 넣고 sort(), 하나씩 빼면서 시뮬레이션
게임 오버 연출
- 갑자기 UI 다 꺼지고 흑백이 됨.
- 화면이 깨짐.
- 해결은 거의 다 해서 이제 씬에서 몇 개 좀 건드리고 코드만 적으면 구현 끝인데, 시간이 늦어서 정신이 어지러움. 내일 자고 일어나서 마저.