스마일 체리

스마일 체리게임은 내 글(1년 회고록)에서 여러번 언급되지만, 나의 첫 게임 프로젝트였다.

게임 플레이 영상

지금 봐도 프로그래머가 처음 시작한 프로젝트 치고 퀄리티가 좋았다.

저 당시 휴학중이기도 했고, 오로지 프로젝트에만 전념해서 개발을 이어가던 시기라 코드적으로 완성도가 없더라도 프로젝트 자체에는 신경을 되게 많이 썼다.

SGM이라는 자리와 생각보다 좋은 성과, 마음에 잘 맞는 팀이 공존해서 운이 좋게 좋은 스타트를 시작했다고 본다.

당시에 객체지향의 자도 모를 시기라 되게 많은 우여곡절을 겪기도 하고, 팀원끼리의 마찰이나 협업에서 발생하는 문제점들이 참 많았다.

1년이나 같이 프로젝트를 하다보면 정말 다양한 일이 생긴다.

몇 가지 기억나는 코드

당시 프로그래머가 2명으로 한분은 UI쪽을 맡고 나는 인게임의 전반을 담당했다. (나는 당시 프로젝트가 하나지만 그분은 여러 프로젝트를 작업 중이였다.)

모든 게 처음이라 만나는 문제마다 벽이였고, 이 시기에 가장 많은 성장을 했다고 생각한다.

물론 반면교사도 많이 생겼다.

그 중에 가장 기억나는 문제점이 몬스터의 FSM모델을 만들 때 잘 알지도 못하고 억지로 만들려고 했던 것이 가장 기억에 남는다.

당시 프로그래밍 패턴을 꼭 적용해야 하는 줄 알고 공부 후 억지로 적용하려 했다가 오히려 코드 구조가 망가졌던 경험이 있다.

중복도 많아지고, 캡슐화는 깨지고 제대로 동작은 하지만 잘 짠 코드가 아니라는 점은 명확하게 알고 있었다.

그 코드를 고치는 것과 그대로 두는 것에 대해서 많은 고민을 했었다. (이미 진흙탕에 빠져버린 코드)

당시 코드를 좀 보면 State 패턴의 형태로 FSM모델을 만들었는데.

States[(int)Enums.MonsterStates.Idle] = bombMonsterIdleState;
States[(int)Enums.MonsterStates.Walk] = bombMonsterWalkState;
States[(int)Enums.MonsterStates.Trace] = bombMonsterTraceState;
States[(int)Enums.MonsterStates.Attack] = bombMonsterAttackState;
States[(int)Enums.MonsterStates.Hit] = bombMonsterHitState;
States[(int)Enums.MonsterStates.Die] = bombMonsterDieState;
States[(int)Enums.MonsterStates.Global] = bombMonsterGlobalState;

문제는 추상화 계층을 생각하지 않고 만들어서 각 상태마다 모든 상태 즉, State클래스를 만들어야 했던 기억이 있다.

결국 조금의 수정만 하고 좋은 반면 교사로 남았던 기억이 있다.

States[(int)Enums.MonsterStates.Idle] = MonsterIdleState;
States[(int)Enums.MonsterStates.Walk] = MonsterWalkState;
States[(int)Enums.MonsterStates.Trace] = MonsterTraceState;
States[(int)Enums.MonsterStates.Attack] = MonsterAttackState;
States[(int)Enums.MonsterStates.Hit] = MonsterHitState;
States[(int)Enums.MonsterStates.Die] = MonsterDieState;
States[(int)Enums.MonsterStates.Global] = MonsterGlobalState;

기본 상태가 추가됨으로 전체적인 클래스가 줄어들긴 함

저 당시는 생각하지 못했지만 지금 생각할 수 있는 부분은 인터페이스로 교체하고 각 상태를 좀 더 유연하게 다룰 수 있을 것 같다.

아니면 각 상태에 대해서는 state 확장이 아닌 strategy쪽으로 돌려서 만들어도 좋다고 본다.

하지만 문제는 이 주입 과정도 리터럴로 몬스터마다 클래스가 박혀 있고 이를 제공해주는, DI해주는 모델이 없어서 코드가 많이 더러워 보이는 것 같다.

사실 지금 다루는 몇 가지 코드는 정말 작은 부분이라.. (정말 코드의 양이 엄청나다)

그래도 보스 같은 경우에는 패턴을 만들기 위해 공격 자체에 산하로 패턴을 여러개 둔 형태는 지금 생각해보면 잘 한 것 같다는 생각도 든다.

그외에 가장 시간을 많이 쓴 스파인 관련 코드나 액션감을 만들기 위해 플레이어에 정말 많은 수치가 들어갔다는 점이다.

  gravityStrength: -156.25
  gravityScale: 5.2083335
  fallGravityMult: 2
  maxFallSpeed: 15
  fastFallGravityMult: 3
  maxFastFallSpeed: 18
  runMaxSpeed: 8
  runAcceleration: 7
  runAccelAmount: 43.75
  runDecceleration: 7
  runDeccelAmount: 43.75
  accelInAir: 1
  deccelInAir: 1
  doConserveMomentum: 0
  jumpHeight: 8
  jumpTimeToApex: 0.32
  jumpForce: 50
  jumpCutGravityMult: 2.3
  jumpHangGravityMult: 1
  jumpHangTimeThreshold: 0
  jumpHangAccelerationMult: 1
  jumpHangMaxSpeedMult: 1
  wallJumpForce: {x: 17, y: 34}
  wallJumpRunLerp: 0.05
  wallJumpTime: 0.06
  doTrunOnWallJump: 0
  slideSpeed: -3
  slideAccel: 12
  coyoteTime: 0.2
  jumpInputBufferTime: 0.2
  dashAmount: 1
  dashSpeed: 30
  dashSleepTime: 0.05
  dashAttackTime: 0.2
  dashEndTime: 0.15
  dashEndSpeed: {x: 15, y: 15}
  dashEndRunLerp: 0.5
  dashRefillTime: 0.5
  dashInputBufferTime: 0.1
  boosterAmount: 1
  boosterSpeed: 100
  boosterInputBufferTime: 0.1

사실 실제 서비스되는 게임에 비해서는 적은 수치라고 생각될 수 있어도 당시에는 저 수치를 계산하는 수학이 정말 싫었던 기억 있다.

실제로 팀원과 이야기 해보면서 액션감, 조작감을 개선할 방법을 찾아볼려고 했지만 개선방법이 크게 없었다.

QA를 통해 사람들의 의견을 들어도 플레이 스타일에 따라 피드백이 천차만별이고 (과연 신뢰할 수 있는 피드백인가?) 더 나아지는 방법은 프로그래머인 내가 계속 개선해 나가는 것인데, 그 부분에서 많은 고민을 했었다.

생각해보니 조작감은 단순 키 입력이 아니라 해당 게임에 맞는 스타일을 유지하는 것이라 생각되고 액션감은 정말 디테일한 부가적인 요소가 중요해 보인다.

새로운 기술의 무리한 도입

몇 가지 실수라면 당시 “바퀴를 다시 만들지 마라”라는 말에 빠져서 억지로 도입한 몇 가지 라이브러리들이 있다.

기억 나는 건, 시네머신(잘 사용도 못하면서..), UniRx

절대로 사용하지 말라는 말이 아니다.

기본적인 사용방법을 모르거나 장점과 단점을 비교해보지도 않고 기술을 위한 프로젝트를 진행하면 안된다는 것이다.

코드도 마찬가지지만 “새로운 게 좋다, 신 기술 최고”라는 마인드는 위험할 수 있다.

비교 대상을 두고 장점과 단점을 생각하고 적용하는 것은 좋지만 프로젝트에 필요하지 않지만 좋다고 하니 적용하는 것은 위험성이 크게 증가한다.

당시 개발자가 나 혼자였기 때문에 저런 모험에 대해서 제지해주는 사람이 없었다는 점이 조금 아쉽다.

협업의 문제점

당시 팀은 나를 제외한 모두가 취준생이였고, 흔한 인디게임팀으로 그냥 비대면으로 작업을 이어가던 팀이였다.

팀원은 서로에 대한 이해는 어느정도 있었지만 신뢰나 솔직함은 부족했던 것 같다.

처음 협업에서 조금 문제점을 발견한 것은 팀원끼리의 친밀도가 너무 높다보니 해야할 말을 하지 않게 되는 것이였다.

지금에서야 느끼지만 솔직함은 문제되지 않는다. 오히려 솔직하게 말하지 못하는 것이 문제가 더 크게 굴러왔던 것 같다.

내가 가장 크게 한 실수는 타인이 자신과 다르다는 점을 인정하지 못한 것 같다.

팀원들은 취준생이 많았기 때문에 적당한 포폴로 마무리하고 싶은 인원이 더 많았으며, 팀원 마다의 목표가 달랐기 때문에 나오는 문제가 있었다.

PM의 부재도 컸다.

당시에 여러번 넘어질 뻔 한적이 있었는데 그 때 마다 좀 더 현실적으로 바라보기 위해 팀원들에게 제안을 많이 했던 것 같다.

그 당시에도 가능하다면 PM을 제안 했었는데, 너무 겁이나고 지쳐서 거절했던 기억이 있다.

이후로 필요성을 느끼고 관리하는 방법론이나 인간관계에 관한 공부도 지속했다.

PM이란?

마무리

현재 팀원들은 나를 제외하면.. (당시 대학교 2학년) 대다수가 취업에 성공했다.

좋은 프로젝트였고, 나름 첫 프로젝트 치고는 좋은 경험이 더 많았다.

흔히 게임 업계에서 쓰는 말인 “처음 만드는 10개의 게임은 그냥 똥이다.”라는 말처럼 아직까지는 수습생의 코드와 시선으로 게임을 만들어 나갈 뿐이다.

성장에는 항상 목말라하는 부분들이 위 회고록에서 드러나는 것 같다.

작성한 코드를 봐도 뭔가를 적용해보고 싶어서 노력한 부분들이 보이기 때문에 (당시에는 좋은 방법은 아니였다.)

팀원들도 연말에 만나서 다 같이 놀기로 했고 (시험기간이라.. 나만 못가는..ㅠ) 좋은 팀으로 가기 위한 성장과정이였다.

태그: ,

카테고리:

업데이트:

댓글남기기