GameManager 신 개체를 피하는 방법?


51

방금 게임 코드 구성에 관한 질문에 대한 답변을 읽었습니다 . 유비쿼터스 GameManager클래스와 프로덕션 환경에서 얼마나 자주 문제가되는지 궁금해졌습니다 . 이것을 설명하겠습니다.

먼저 프로토 타이핑이 있습니다. 훌륭한 코드 작성에 신경 쓰지 않는 사람은 게임 플레이가 추가되는지 확인하기 위해 무언가를 실행하려고합니다.

초록 빛이 있고, 물건을 정리하기 위해 누군가가을 씁니다 GameManager. 아마도 많은 것을 보관하고 GameStates, 아마도 몇 개를 저장하고 GameObjects, 아무것도 크지 않을 것입니다. 귀엽고 작은 매니저

사전 제작의 평화로운 영역에서 게임은 멋지게 형성되고 있습니다. 코더는 훌륭한 디자인 패턴으로 물건을 건축 할 수있는 적절한 수면과 아이디어를 가지고 있습니다.

그런 다음 생산이 시작되고 곧 위기 시간이 있습니다. 균형 잡힌 식단은 오랫동안 사라졌고, 버그 추적기는 문제로 크래킹되고, 사람들은 스트레스를 받고 게임은 어제 출시되어야합니다.

그 시점에서, 일반적으로는 GameManagerA는 실제 큰 혼란은 (정중 유지하기 위해).

그 이유는 간단합니다. 게임을 작성할 때 결국, 잘 ... 모든 소스 코드가 실제로 여기에 관리 게임 . 이 작은 추가 기능이나 버그 수정을에 추가하는 것은 쉽습니다 GameManager. 다른 모든 것이 이미 저장되어 있습니다. 시간이 문제가 될 때 별도의 수업을 쓰거나이 거대한 관리자를 하위 관리자로 나눌 수 없습니다.

: 물론 이것은 고전적인 안티 패턴 신 객체 . 나쁜 일, 합병하는 고통, 유지해야 할 고통, 이해해야 할 고통, 변화하는 고통입니다.

이런 일이 발생하지 않도록 무엇을 제안 하시겠습니까?

편집하다

나는 네이밍을 비난하고 싶은 유혹을 느낀다. 물론 수업을 만드는 GameManager것은 그리 좋은 생각이 아닙니다. 그러나 같은 일이 깨끗한 일어날 수 있습니다 GameApplication하거나 GameStateMachine또는 GameSystem그 프로젝트의 말까지 덕트 테이프 좋아하는 것으로 끝납니다. 네이밍에 관계없이 게임 코드 어딘가에 클래스가 있습니다. 지금은 배아 일뿐입니다. 어떤 몬스터가 될지는 아직 모릅니다. 그래서 나는 "네임 비난"이라는 대답을 기대하지 않습니다. 이 문제가 발생하는 것을 막을 방법, 코딩 아키텍처 및 / 또는 팀이 따라갈 수있는 프로세스가 프로덕션의 어느 시점에서 일어날 지 알고 싶습니다. 한 달 동안의 버그 수정 및 최신 기능을 버리는 것은 너무 나쁩니다. 모든 기능이 유지 관리 할 수없는 한 명의 관리자에게 있기 때문입니다.


GameManager 또는 ControllerOfTheGame 또는 호출하고자하는 모든 것이 든, 전체 게임의 로직을 제어하는 ​​클래스를 피하십시오. 전화를 걸 계획에 관계없이 할 때하는 일을 알고 있습니다. 저의 마지막 게임에는 레벨 컨트롤러가 있었기 때문에 레벨의 상태를 저장하기 시작했습니다.
brandon

@brandon 내가 당신을 위해 나의 질문을 바꾸어 보자. GameManager위에서 설명한 효과에 자신을 노출시키지 않고 전체 게임의 논리를 어떻게 제어 합니까?
Laurent Couvidou

논리에 따라 다릅니다. 자신 만의 논리를 가지고있는 플레이어, 적, 구조 등과 같은 명백한 것들이 각자의 클래스에 적용됩니다. 당신이 가장 궁금해하는 것은 게임의 상태를 다루는 것입니다. 일반적으로 전체 게임의 상태를 추적하는 클래스가 있지만 내 경험상 프로토 타이핑 할 때 걱정해야 할 마지막 항목 중 하나이며 목적은 매우 명확해야합니다. 기본적으로 프로토 타입을 작성하기 전에 초기 계획을 세우거나 테스트를위한 정크 클래스를 사용하지 않도록 프로덕션을 시작할 때 처음부터 시작합니다.
brandon

흥미롭게도 XNA는 이러한 잠재적 인 재난을 초래합니다. 기본적으로 Game 클래스는 모든 것을 관리하기 위해 만들어집니다. 기본 업데이트, 그리기, 초기화 및로드 방법이 포함되어 있습니다. 실제로 (새롭지 않은) 게임이 해당 클래스에 포함 된 모든 항목을 관리하기가 너무 어려워서 실제로 새 프로젝트로 마이그레이션하는 중입니다. 또한 Microsoft 자습서가 권장하는 것 같습니다.
Fibericon

답변:


23

초록 빛이 있고, 정리하기 위해 누군가가 GameManager를 작성합니다. 아마도 많은 GameState를 보유하고있을 수도 있고, 실제로는 크지 않은 몇 개의 GameObject를 저장할 수도 있습니다. 귀엽고 작은 매니저

내가 이것을 읽을 때, 나는 머리에 작은 경보가 울렸다. "GameManager"라는 이름의 오브젝트는 결코 귀엽거나 작을 수 없습니다. 그리고 누군가 코드를 정리하기 위해 이것을 했습니까? 전에는 어땠나요? 좋아, 농담은 제쳐두고 : 클래스의 이름은 클래스의 역할을 명확하게 나타내야하며 이것은 하나의 책임 이어야합니다 (일명 책임 원칙 ).

또한 GameManager와 같은 객체가 여전히 생길 수 있지만 분명히 매우 높은 수준으로 존재하므로 높은 수준의 작업과 관련이 있습니다. 게임 오브젝트의 카탈로그를 유지합니까? 혹시. 게임 개체 간의 커뮤니케이션을 촉진 하시겠습니까? 확실한. 객체 간 충돌을 계산합니까? 아니! 그렇기 때문에 이름 관리자 가 눈살을 찌푸리는 이유도 있습니다. 너무 광범위해서 배너 아래에서 많은 악용이 가능합니다.

수업 규모에 대한 간단한 경험 법칙 : 수업 당 수백 줄의 코드를 실행하면 문제가 발생하기 시작합니다. 300 LOC는 지나치게 열악하지 않고 코드 냄새가 나며, 1000 개가 넘으면 경고음이 울려 야합니다. 어떻게 든 1000 줄의 코드가 각각 250 개의 4 개의 잘 구조화 된 클래스보다 이해하기 쉽다고 믿으면서 스스로를 속이고 있습니다.

시간이 문제가 될 때 별도의 수업을 쓰거나이 거대한 관리자를 하위 관리자로 나눌 수 없습니다.

문제가 모든 것이 엉망인 지점으로 전파 될 수 있기 때문에 이것이 사실이라고 생각합니다. 의 연습 리팩토링은 - 당신이 찾고있는 무엇을 정말 당신은 지속적으로 작은 단위로 코드의 디자인을 개선하기 위해 필요합니다 .

이런 일이 발생하지 않도록 무엇을 제안 하시겠습니까?

문제는 기술적 인 문제가 아니므로 기술적 인 문제를 찾아서는 안됩니다. 문제는 이것입니다. 팀에서 모 놀리 식 코드 조각을 만드는 경향이 있으며, 이와 같이 작동하는 것이 중장기 적으로 유리하다는 믿음이 있습니다. 또한 팀에는 강력한 아키텍처 리더가 부족하여 게임의 아키텍처를 조정합니다 (적어도이 사람은이 작업을 수행하기에는 너무 바쁩니다). 기본적으로, 유일한 방법은 팀 구성원이이 생각이 잘못되었음을 인식하도록하는 것입니다. 아무도 호의를 베풀지 않습니다. 제품의 품질이 떨어지고 팀은 물건을 수리하는 데 더 많은 밤을 보낼 것입니다.

좋은 소식은 깨끗한 코드 작성의 즉각적이고 실질적인 이점이 너무 커서 거의 모든 개발자가 자신의 이점을 매우 빠르게 인식한다는 것입니다. 팀이 한동안 이런 식으로 일하도록 설득하면 결과는 나머지 작업을 수행합니다.

어려운 부분은 나쁜 코드를 구성하는 요소에 대한 느낌을 개발하는 것 (그리고 더 나은 디자인을 빠르게 만들 수있는 재능)이 개발에서 배우기가 더 어려운 기술 중 하나라는 것입니다. 내 제안은 당신이 이것을 할 수있는 팀에 선임자가 있다는 희망에 달려 있습니다. 사람들을 그렇게 설득하는 것이 훨씬 쉽습니다.

편집-조금 더 많은 정보 :

일반적으로 귀하의 문제는 게임 개발에만 국한되지 않는다고 생각합니다. 핵심은 소프트웨어 엔지니어링 문제이므로 그 방향에 대한 의견입니다. 다른 유형의 개발보다 더 많은 결과와 마감일을 지향하는지 여부에 관계없이 게임 개발 산업의 성격이 다를 수 있습니다.

그러나 특히 게임 개발의 경우 "특히 게임 아키텍처"팁과 관련하여 StackOverflow에 대한 이 질문 에 대한 대답 은 다음과 같습니다.

객체 지향 디자인견고한 원칙을 따르십시오 ....

이것은 본질적으로 내가 말하는 것입니다. 압력을 받고있을 때, 나는 또한 큰 코드를 작성하고 있다는 것을 알게되었지만 기술 부채라는 것을 내 머리에 뚫었습니다. 나를 위해 잘 작동하는 것은 하루 중 상반기 (또는 4 분의 3)를 대량의 중간 품질 코드를 생성 한 다음 잠시 후 다시 생각하고 생각하는 것입니다. 코드를 약간 향상시키는 방법에 대해 머리 또는 종이 / 화이트 보드에서 약간의 디자인을하십시오. 종종 반복적 인 코드를 발견하고 실제로 가독성을 향상시키면서 모든 것을 줄임으로써 전체 코드 줄을 줄일 수 있습니다. 이번 투자는 너무 빨리 돈을 지불하여 "투자"라고하는 것은 어리석은 소리로 들립니다. 아주 자주 나는 하루 종일 (1 주일 후) 낭비했을 수있는 버그를 발견 할 것입니다.

  • 코딩 한 당일에 문제를 해결하십시오.
  • 몇 시간 안에 기뻐하실 것입니다.

실제로 위의 내용을 믿기가 어렵습니다. 나는 효과를 반복해서 경험했기 때문에 내 일을 위해서만 해냈습니다. 그럼에도 불구하고 더 많은 정보를 얻을 수있을 때 코드 수정을 정당화하는 것은 여전히 ​​어렵습니다 ... 그래서 나는 당신이 어디에서 왔는지 확실히 이해합니다. 불행히도이 조언은 너무 일반적 일 수 있으며 쉽지 않습니다. 그러나 나는 그것을 강력하게 믿는다! :)

구체적인 예를 들면 다음과 같습니다.

Uncle Bob의 Clean Code 는 양질의 코드가 어떤 것인지 요약하는 놀라운 일을합니다. 나는 거의 모든 내용에 동의합니다. 따라서 30 000 LOC 관리자 클래스의 예를 생각할 때 "좋은 이유"부분에 실제로 동의 할 수 없습니다. 나는 불쾌하게 말하고 싶지 않지만 그런 식으로 생각하면 문제가 발생할 수 있습니다. 단일 파일에 많은 코드를 넣을 이유가 없습니다. 거의 1000 페이지의 텍스트입니다! 로컬 리티 (실행 속도 또는 디자인 "단순성")의 이점은 개발자가 그 괴물을 탐색하려고 완전히 쇠약 해져서 즉시 무시됩니다.

확신이 없으면 위의 책의 사본을 들고 살펴 보는 것이 좋습니다. 이러한 유형의 사고를 적용하면 사람들이 자발적으로 깨끗하고 자명 한 코드를 만들 수 있습니다.


이것은 한 번 본 결함이 아닙니다. 여러 프로젝트에서 여러 팀에서 이것을 보았습니다. 나는이 문제로 어려움을 겪고있는 많은 재능 있고 구조화 된 사람들을 보았다. 압력이 가해지면 300 줄의 코드 제한은 생산자가 신경 쓰는 것이 아닙니다. 플레이어도 마찬가지입니다. 물론 이것은 좋고 달콤하지만 악마는 세부 사항에 있습니다. GameManager내가 지금까지 본 최악의 경우 는 약 30.000 줄의 코드였으며, 대부분의 이유는 여기에 있다고 확신합니다. 이것은 물론 극단적 인 일이지만 실제 상황에서 발생합니다. 나는이 GameManager효과 를 제한하는 방법을 요구하고 있습니다.
Laurent Couvidou

@lorancou-게시물에 상당히 많은 정보를 추가했습니다. 댓글에 너무 많은 정보가 있었으므로 콘크리트 건축을 가리킬 수 없어도 조금 더 많은 아이디어를 제공하기를 바랍니다. 예.
Daniel B

아, 나는 그 책을 읽지 않았으므로 확실히 좋은 제안입니다. 아, 그리고 수천 줄의 클래스에 코드를 추가해야 할 이유가 있다는 것을 의미하지는 않았습니다. 그런 종류의 신 객체의 모든 코드 유용한 것을 수행한다는 것을 의미했습니다 . 아마 아마 너무 빨리 쓴;)
Laurent Couvidou

@lorancou Hehe, 그거 좋은데 ... 그 방법은 정신 이상입니다 :)
Daniel B

"리팩토링의 실습은 여러분이 찾고있는 것입니다. 코드 디자인을 조금씩 지속적으로 개선해야합니다." 나는 당신이 거기에 매우 강한 지적을 가지고 있다고 생각합니다. 엉망은 엉망을 불러 일으키고, 이것이 진짜 이유이기 때문에 엉망은 장기간 싸워야합니다. 나는이 대답을 받아 들일 것이지만 다른 것에는 가치가 없다는 것을 의미하지는 않습니다!
Laurent Couvidou

7

이것은 실제로 게임 프로그래밍의 문제가 아니라 일반적인 프로그래밍의 문제입니다.

모든 소스 코드는 실제로 게임을 관리하기 위해 여기에 있습니다.

그렇기 때문에 이름에 "Manager"가있는 클래스를 제안하는 객체 지향 코더에서 눈살을 찌푸려 야합니다. 공평하게 말하면, 게임에서 "반신"물체를 피하는 것은 사실상 불가능하다고 생각하지만 "시스템"이라고 부릅니다.

마감일이 가까워지면 소프트웨어가 더러워지는 경향이 있습니다. 그것은 일의 일부입니다. " 덕트 타입 프로그래밍 "에는 본질적으로 잘못된 것이 없습니다 . 특히 몇 시간 안에 제품을 배송해야 할 때 특히 그렇습니다. 이 문제를 완전히 제거 할 수는 없으며 간단히 줄일 수 있습니다.

분명히 GameManager에 물건을 넣고 싶은 유혹을 받으면 매우 건강한 코드 기반이 없다는 것을 의미합니다. 두 가지 문제가있을 수 있습니다.

  • 코드가 너무 복잡합니다. 너무 많은 패턴, 조기 최적화, 아무도 더 이상 흐름을 이해하지 못합니다. 가능한 경우 개발할 때 더 많은 TDD를 사용하십시오. 복잡성과 싸우는 매우 좋은 솔루션이기 때문입니다.

  • 코드가 제대로 구성되지 않았습니다. 전역 변수를 사용하고 있으며 클래스가 느슨하게 연결되어 있지 않으며 인터페이스도없고 이벤트 시스템도 없습니다.

코드가 제대로 보이면 각 프로젝트마다 "무슨 일이 있었는지"기억하고 다음에 코드를 피해야합니다.

마지막으로 팀 관리 문제 일 수도 있습니다. 충분한 시간이 있었습니까? 모두가 당신이 가고있는 건축에 대해 알고 있었습니까? 도대체 "Manager"라는 단어가있는 클래스로 커밋을 허용 한 사람은 누구입니까?


덕트 테이프 프로그래밍에는 아무런 문제가 없습니다. 그러나 나는 확실히 관리자 클래스가 게임 엔진에 있다고 확신합니다. 적어도 많이 보았습니다. 너무 커지지 않는 한 유용합니다 ... a SceneManager또는 a 의 문제점은 무엇입니까 NetworkManager? 왜 우리가 그것들을 막아야하는지, 또는 -Manager를 -System으로 바꾸는 것이 어떻게 도움이되는지 모르겠습니다. 나는 일반적으로 GameManager코드가 부패하기 쉬운 대체 아키텍처에 대한 제안을 찾고 있습니다.
Laurent Couvidou

SceneManager에 어떤 문제가 있습니까? 음, Scene과 SceneManager의 차이점은 무엇입니까? 네트워크 및 네트워크 관리자? 다른 측면에서 : 이것은 아키텍처 문제라고 생각하지 않지만 GameManager에 있고 거기에없는 무언가에 대한 구체적인 예를 제시 할 수 있다면 해결책을 제안하는 것이 더 쉬울 것입니다.
Raveline

좋아, 그래서 -Manager 일을 잊어라. 게임 상태를 처리하는 클래스가 있다고 가정 해 봅시다 GameStatesCollection. 처음에는 몇 가지 게임 상태와 그 사이를 전환하는 방법이 있습니다. 그런 다음 로딩 화면이 와서이 모든 것을 복잡하게합니다. 그런 다음 Level_A에서 Level_B로 전환하는 동안 사용자가 디스크를 꺼내면 일부 프로그래머가 버그를 처리해야하며 반나절 리팩토링없이 디스크를 고치는 유일한 방법은입니다 GameStatesCollection. 붐, 신의 대상.
Laurent Couvidou

5

따라서 더 많은 엔터프라이즈 환경에서 가능한 한 가지 솔루션을 제공합니다. 제어 / 종속성 주입의 반전을 확인 했습니까?

기본적으로 게임의 다른 모든 것을위한 컨테이너 인 이 프레임 워크 를 얻 습니다. 단지 모든 것을 함께 연결하는 방법과 객체 간의 관계가 무엇인지 알고 있습니다. 어떤 객체도 자신의 생성자 내에서 아무것도 인스턴스화하지 않습니다. 오히려 그들은, 그들이 필요한 것을 만드는 것보다 물어 그들은 IOC의 프레임 워크에서 필요한 것을 위해; IoC 프레임 워크는 생성시 종속성을 충족시키는 데 필요한 개체를 "알고"채 웁니다. 느슨한 커플 링 FTW.

EnemyTreasure 클래스가 컨테이너에 GameLevel 객체를 요청하면 프레임 워크는 어떤 인스턴스를 제공할지 알고 있습니다. 어떻게 알 수 있습니까? 어쩌면 더 일찍 인스턴스화했을 수도 있고 근처 GameLevelFactory에 물어볼 수도 있습니다. 요점은 EnemyTreasure는 GameLevel 인스턴스의 출처를 모릅니다. 그것은 그 의존성이 이제 만족되고 그것의 인생을 계속할 수 있다는 것을 알고 있습니다.

오, PlayerSprite 클래스가 IUpdateable을 구현하는 것을 보았습니다. 프레임 워크는 모든 IUpdateable 객체를 기본 게임 루프가있는 타이머에 자동으로 구독하기 때문에 좋습니다. 모든 Timer :: tick ()는 모든 IUpdatedable :: update () 메소드를 자동으로 호출합니다. 쉬워요?

현실적으로이를 위해이 bighugeohmygod 프레임 워크가 필요하지 않습니다. 중요한 부분을 직접 수행 할 수 있습니다. 요점은 -Manager 유형 객체를 만드는 것을 발견하면 클래스간에 책임을 올바르게 분배하지 못하거나 어딘가에 일부 클래스가 누락 된 것입니다.


IoC에 대해 처음 들어 봤습니다. 이것은 게임 프로그래밍에는 너무 큰 것이 될 수 있지만 확인해 보겠습니다!
Laurent Couvidou

IoC, 그냥 상식이라고 부르지 않았습니까?
brice

반 기회가 주어지면 엔지니어는 무엇이든 프레임 워크를 만들 것입니다. (= 게다가, 나는 프레임 워크를 사용하는 것을 옹호하지 않고, 건축 패턴을 옹호합니다.
drhayes

3

과거에는 일반적으로 다음을 수행하면 신 수업으로 끝납니다.

  • 클래스 다이어그램을 작성하기 전에 게임 편집기 / IDE / 메모장에 앉아 있거나 주 개체의 스케치 만합니다.
  • 게임에 대한 매우 모호한 아이디어로 시작하여 즉시 코딩 한 다음 새로운 아이디어가 나오면 반복하십시오.
  • GameManager가 실제로 도메인 객체 인 턴 기반 전략과 같은 상태 기반 게임을 만들지 않을 때 GameManager라는 클래스 파일을 만듭니다.
  • 초기에 코드 구성에 신경 쓰지 마십시오

논란의 여지가 있을지 모르지만, 프로토 타입을 만들 때조차도 한 번은 생각할 수 없어서 재생 가능한 프로토 타입을 작성하기 전에 매우 기본적인 클래스 다이어그램을 작성해서는 안됩니다. 계획하기 전에 기술 아이디어를 테스트하는 경향이 있지만 그게 전부입니다. 포탈을 만들고 싶다면 포탈을 작동시키기위한 매우 기본적인 코드를 작성하고 약간의 계획을 세우기 위해 좋은 시간을 보낸 다음 재생 가능한 프로토 타입으로 작업 할 수 있습니다.


1

나는이 질문이 오래되었다는 것을 알고 있지만 2 센트를 더할 것이라고 생각했습니다.

게임을 디자인 할 때는 거의 항상 Game 객체가 있습니다. 그러나, 그것은 매우 높은 수준이며 실제로 "무엇을"하지 않습니다.

예를 들어, Graphics 클래스에 Render를 지시하지만 렌더링 프로세스와는 아무런 관련이 없습니다. LevelManager에 새 레벨을로드하도록 요청할 수 있지만로드 프로세스와는 아무런 관련이 없습니다.

요컨대, 나는 반신과 같은 객체를 사용하여 다른 클래스의 사용을 조정합니다.


2
이것은 전혀 신과 같지 않습니다. 이것을 추상화라고합니다. :)
Vaughan Hilts
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.