250802

凡愚·2025년 8월 2일

개발 일지

목록 보기
251/350

🕹️ 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 다 꺼지고 흑백이 됨.
  • 화면이 깨짐.
    • https://www.youtube.com/watch?v=VvxhH0at4Ss
    • Blender UV 관련 뻘짓 좀 함. 손으로 일일이 지정해야 했음.
    • UV 제대로 설정했는데도 데칼코마니처럼 돼있었음. 3D 오브젝트라서 Unlit 해주니까 정신차림.
  • 해결은 거의 다 해서 이제 씬에서 몇 개 좀 건드리고 코드만 적으면 구현 끝인데, 시간이 늦어서 정신이 어지러움. 내일 자고 일어나서 마저.

0개의 댓글