카테고리 없음

프로젝트- cctv벽 개발 (하나의 기능을 완성하기 위한 3번의 피봇)

aerimi-code 2025. 9. 23. 14:18

이번 프로젝트에서 나는 'CCTV 벽'이라는 하나의 기능을 개발하는 임무를 맡았다. 처음에는 맵의 분위기를 살리는 장식적 요소라고 가볍게 생각했지만, 이 기능 하나를 완성하기까지 무려 세 번의 방향 전환(Pivot)을 겪으며 개발자로서 가장 큰 성장을 경험했다.



1: "플레이어를 추적하라!" - 잘못된 이해와 기술적 도전

처음 기획서를 봤을 때, 나는 '플레이어가 감지되면 CCTV들이 플레이어를 따라다니는' 인터랙티브한 장식물이라고 이해했다. 명확한 설계가 없었기에, 내 상상력을 발휘하여 개발을 시작했다.

기획 문서에 있던 설계 그림만 존재하고 이에 대한 설명이 존재하지 않았다..

 

 

단순히 2D 스프라이트를 플레이어 방향으로 뒤집고(flip), 따라가게만 하면 될 줄 알았다. 하지만 현실은 달랐다. 쿼터뷰 시점의 3D 공간에서 2D 스프라이트를 자연스럽게 특정 대상을 바라보게 만드는 것은 수많은 계산이 필요한 일이었다.

  • 문제: 각도에 따라 스프라이트 Flip이 왜곡되고, 오브젝트 중심축 문제로 자연스러운 추적이 불가능했다.
  • 해결: 나는 'Aimer'라는 빈 오브젝트를 플레이어 주변에 생성하고, CCTV의 카메라 부분이 이 Aimer를 보도록 로직을 짰다. 플레이어와 CCTV의 벡터 계산으로 좌우를 구분해 Flip을 제어하고, 코루틴으로 추적과 대기 상태를 구현하여 그럴듯한 추적 CCTV를 완성했다. 나아가 플레이어가 없을 땐 지정된 타겟들을 랜덤하게 순찰하는 기능까지 함수화하여, 하나의 함수로 플레이어 추적과 랜덤 순찰을 모두 처리할 수 있는 효율적인 코드를 설계했다.


초기 모습: cctv 아트도 없어서 그냥 아트중 적절한 아트 찾아서 적용

 

이때까지만 해도, 나는 꽤 똑똑한 설계를 했다고 생각했다.

2: "추적하지 않아요." - 기획의 반전과 진짜 난관

자신 있게 완성한 기능을 기획님께 보여드렸을 때, 돌아온 답변은 내 예상을 완전히 빗나갔다. "어? 플레이어를 추적하지 않아요. 무작위로 빛을 비추고, 그 빛에 닿으면 데미지를 입는 함정이에요."

좌절감이 몰려왔지만, 동시에 내가 만든 함수 덕분에 수정은 간단했다. 플레이어 추적 로직만 제거하면 됐기 때문이었다. 하지만 진짜 문제는 이제부터였다. 바로 '빛'의 구현이었다.

  • 문제: 2D 스프라이트로 만든 빛을 쿼터뷰 각도에 맞춰 자연스럽게 뻗어 나가게 표현하는 것이 거의 불가능했다. 또한, 스프라이트 빛이 어떻게 플레이어와의 충돌을 감지할 수 있을까?


빛 이미지


시도 1: ProBuilder로 빛 스프라이트 모양 그대로 3D Mesh Collider를 만들었다. 충돌 감지는 성공했지만, 빛이 바닥에 깔린 평면처럼 보여 입체감이 전혀 없었다.

 


3: "보여줘라." - 두 번의 깨달음과 최종 완성

벽에 부딪혔을 때, 멘토링과 새로운 발상을 통해 해결의 실마리를 찾았다.

  • 첫 번째 깨달음 (멘토링): "실시간으로 모든 각도를 계산하려 하지 말고, 미리 만들어둔 여러 각도의 CCTV 상태(오브젝트)를 상황에 맞게 켜고 끄는 방식은 어때요?" 이 피드백은 혁신적이었다. 나는 즉시 여러 각도를 바라보는 6개의 CCTV 오브젝트 배열을 만들고, 랜덤 타겟 배열과 인덱스를 맞춰 상태를 전환하는 코드를 작성했다. '실시간 계산'이라는 어려운 길 대신, '미리 정의된 상태'를 보여주는 방식으로 접근하자 훨씬 섬세하고 안정적인 제어가 가능해졌다.

빛이 스포트라이트처럼 퍼진다. 6가지 상태의 cctv벽 모습을 만든 것

  • 두 번째 깨달음 (발상의 전환): 하지만 빛의 왜곡 문제는 여전했다. 그때 문득, "왜 모든 것을 직접 만들어야 한다고 생각했을까?"라는 생각이 들었다. 유니티를 처음 다루다 보니 에셋 스토어의 존재를 잊고 있었다. 나는 즉시 무료 라이트 에셋을 찾아 적용했다. 핀 조명처럼 아래로 퍼지는 형태의 빛 효과는 바닥에 감지 영역을 표시하기에 완벽했고, 빛 모양에 맞춰 투명한 구체(Sphere Collider)를 isTrigger로 배치하자 모든 것이 해결되었다.



 

마침내, 기획 의도에 맞는 자연스러운 빛을 내뿜는 CCTV 벽이 완성되었다.

느낀점: 이번 개발을 통해 얻은 4가지 성장 키워드

  1. 요구사항 명확화의 중요성: "이거 맞나요?" 개발 시작 전 단 한 번의 질문이, 며칠간의 잘못된 개발을 막을 수 있었다. 이제 나는 기획이 불명확하다면 반드시 명확해질 때까지 질문하고 문서를 통해 확인한다.
  2. 컴퓨터와의 대화법: "컴퓨터는 멍청해서 내가 다 알려줘야 한다"는 말을 되새겼다. 자연스러운 움직임 뒤에는 수많은 개발자의 명시적인 계산과 정의가 있다는 것, 그 정밀함을 구현하는 것이 개발자의 책임임을 깨달았다.
  3. 유연한 사고와 문제 해결: 어려운 길을 고집하는 대신, 멘토링 피드백처럼 **'더 쉬운 길'**을 찾는 유연함과, 에셋 스토어 활용처럼 **'더 효율적인 길'**을 찾는 지혜가 좋은 개발자를 만든다는 것을 배웠다.
  4. 팀원과의 소통과 신뢰: 아티스트에게 "이런 각도의 스프라이트 6개만 그려주세요"라고 명확히 요청했다면, 혼자서 스프라이트를 비틀며 고생할 필요가 없었을 것이다. 각자의 전문성을 믿고 명확하게 소통하는 것이 결국 모두의 수고를 덜고 최고의 결과물을 만든다는 것을 배웠다.




우리 게임에서 필요한 

cctv벽을 개발하기로 했다.

 

문제점 발생: 

우리 게임은 3D 공간에서 2D 스프라이트를 사용한다. 

문제: 

기획에서 명확하게 기능, 설계가 정해지지 않아서 
나는 그냥 장치적 요소라기 보다 맵에 있는 장식물 정도로 생각하고 
열심히 만들었다.. 

내가 이해한 것: 플레이어가 감지되면 플레이어를 cctv들이 플레이어를 추적하는 장식적 요소라고 생각. 

기획 의도: 무작위로 빛을 비추고 해당 빛에 감지된 플레이어는 damage를 입는, 플레이어를 추적하는 것도 아님. 무작위


완전 잘못 생각했다.. 


일단 첫 번째로 내가 이해한 대로 만드는것도 쉽지 않았다. 단순히 cctv를 flip하고 cctv sprite가 플레이어를 따라가면 된다고 생각했는데, 각도에 따라서 flip된게 flip되게 보이지 않을 수도 있고, gameobgect의 중심이 무조건 가운데가 아니기 때문에 플레이어를 단순히 따라간다고 해서 구현이 되지 않았다. 

따라가는 것도 플레이어를 추적해서 따라가는 AI nav 를 사용하면 된다고 생각했지만 이동에 관한 것이기 때문에 플레이어의 추적할 부분을 정하고 그것을 추적하게 설정해야했다. 

또 추적한다는 것을 보여주는 각도도 내가 정해야한다. 컴퓨터는 멍청하다.. 

카메라가 cctv아트 에서 카메라 부분이 플레이어를 보게해야하는데, 컴퓨터는 그걸 모른다.. 내가 결국 하나 하나 다 계산해야하는 것이다. 

어찌어찌해서 aimer라는 오브젝트를 만들어서, 스프라이트가 aimer를 따라가는 형식으로 구현했다. flip은 각도를 고려해서 코드를 구현했고, 플레이어방향-cctvobject의 방향을 빼서 오른쪽인지 왼쪽인지 구분하는 방식을 사용했다.

코루틴을 이용해서 추적 후 잠깐 쉬는 부분도 만들었고,

만들고 나니 플레이어가 감지되지 않을 때는 랜덤으로 움직이는 코드가 필요하다고 생각했다.

cctv감시 구현하기 (플레이어가 감지되지 않을 때)

 

플레이어가 감지되지 않을때는 로봇, 기기처럼 감시하고 있는 모습을 구현해야했다.

근데 이게 위치를 random하게 생성하면 내가 또 그거에 맞춰서 스프라이트를 조정해야할거같은 재앙이 생각났다..

그래서 랜덤위치 타겟들을 오브젝트로 만들고 해당 오브젝트를 배열로 받아서 random하게 target을 설정해서 추적하도록, 설계했다. (똑똑한 설계인것 같다.)

그래서 target을 쫓아가는 걸 함수로 만들고 오브젝트 transform을 인자로 받는 함수로 만들어, randomtarget,playertargetposition 둘다 받을 수 있게 했다. => 이제 함수 하나만 사용하면 된다.


기획님께 확인 받자마자 좌절함 ㅋㅋ. . .  할일이 생겼다.. 빛을 만들어야한다.

플레이어를 쫓아가지 않아요. 이 부분은 수정하기 쉬웠다. 플레이어를 추적하는 부분만 지우면 되기 때문! 

그리고 빛에 관한 부분이 제일 문제였던게 이게 스프라이트라 조절이 상당히 어렵다.. 

그래서 빛을 스프라이트를 조절해서 만들었다. 감지되면 damage를 주는 부분도 만들었다. 
빛이 스프라이트라서 어떻게 감지를 시키지 ? 생각이 들었는데 probuilder를 사용해서 그대로 선을 따서 도형을 만들고 해당 mesh collider를 사용했다. 빛에 닿으면 player damage ! 성공 

=> 문제 발생 평면으로 만드니까 빛이 뭔가 뻗어나간다는 느낌 없음.. 아래에 감지된다는 표시도 없음. 그냥 빛에 닿으면 아픔..

근데, 진짜 어떻게 해도 빛을 앞으로 기울여서 하는게 안됐다.. (이유: 일단 우리 게임은 쿼터뷰임. 45도 45도 기울어져있기 때문에 그렇지 않은 이 벽은 왜곡이 일어남.)

멘토링 때 피드백을 받음. => 그냥 cctv를 상태마다 만들어서 해당 오브젝트를 활성화 하는 방식으로 해라 

오 진짜 좋은 방법이었다. 그러면 aimer도 필요 없고 그냥 어떤 타겟을 감지했냐만 알면 된다. 


=> 타겟배열, cctv배열을 만들어서 cctv의 각도를 조절 (내가 조절할 수 있으니까 굉장히 섬세하게 조절할 수 있었다. 노가다였지만.. ) 

코드는 타겟배열과 cctv배열의 인덱스를 동일하게 변경하는 형식으로 바꿨다.

그러면 감지 & 데미지 위치를 정하는게 쉬워진다. cctv상태가 총 6개니까 감지 위치를 정하면된다.
그래도 문제인게 스프라이트 왜곡이었다.. 

그래서 에셋을 활용해보기로 결정했다. 빛에 관련된 에셋이 있지 않을까? (사실 유니티를 처음 써보는거라 에셋을 쓸 생각을 못해서 처음에 개발할 때 좀 고생했었다.. 에셋 진짜 잘 이용하면 좋은데!!)

무료 빛 에셋을 다운 받아서 적용했다. 해당 에셋을 물체에 닿으면 빛이 퍼지는 형태의 빛이기 때문에 밑에 핀 조명처럼 연출 할 수 있었다. 여기에 빛 모양에 맞춰서 구체를 배치해서 collider 를 is trigger로 설정하여서 원하는 기능을 하는 cctv벽을 만들 수 있었다.



느낀점 

기획이 명확하지 않다면 물어보자.

아트를 내가 만지지 말고 여러개 요청하자. 나만 힘들어진다.. (아트를 내가 다 조절해서 힘들었다. 그냥 앞으로는 아트분께 명확하게 정리해서 요청하기)

개발할 때 컴퓨터가 알아서 처리할거라는 믿음을 버리기. 컴퓨터는 멍청하다 값을 하나하나 다 내가 조절해야한다. 

더 쉬운 방법 찾기.