Top 39 컴포넌트 패턴 Quick Answer

You are looking for information, articles, knowledge about the topic nail salons open on sunday near me 컴포넌트 패턴 on Google, you do not find the information you need! Here are the best content compiled and compiled by the Chewathai27.com/to team, along with other related topics such as: 컴포넌트 패턴 컴포넌트 패턴 예제, C++ 컴포넌트 패턴, 리액트 컴포넌트 패턴, 커맨드 패턴, 프론트엔드 컴포넌트 디자인 패턴, 디자인 패턴, 옵저버 패턴, 게임 전략 패턴


게임용 컴포넌트 디자인 패턴
게임용 컴포넌트 디자인 패턴


C++ 디자인 패턴 13. 컴포넌트 패턴, Component Pattern

  • Article author: boycoding.tistory.com
  • Reviews from users: 2075 ⭐ Ratings
  • Top rated: 3.3 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about C++ 디자인 패턴 13. 컴포넌트 패턴, Component Pattern 컴포넌트 패턴, Component Pattern 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. AI, 물리, 렌더링, 사운드처럼 분야가 다른 코드 … …
  • Most searched keywords: Whether you are looking for C++ 디자인 패턴 13. 컴포넌트 패턴, Component Pattern 컴포넌트 패턴, Component Pattern 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. AI, 물리, 렌더링, 사운드처럼 분야가 다른 코드 … 컴포넌트 패턴, Component Pattern 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. AI, 물리, 렌더링, 사운드처럼 분야가 다른 코드끼리는 최대한 서로 모르는 게 좋다. 이런 코드를 한 클래스 안에..
  • Table of Contents:

C++ 디자인 패턴 13 컴포넌트 패턴 Component Pattern

컴포넌트 패턴 Component Pattern

티스토리툴바

C++ 디자인 패턴 13. 컴포넌트 패턴, Component Pattern
C++ 디자인 패턴 13. 컴포넌트 패턴, Component Pattern

Read More

Chapter 1. 컴포넌트 패턴(Component Pattern) – 평생 공부 블로그 : Today I Learned‍ 🌙

  • Article author: ansohxxn.github.io
  • Reviews from users: 1527 ⭐ Ratings
  • Top rated: 4.4 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about Chapter 1. 컴포넌트 패턴(Component Pattern) – 평생 공부 블로그 : Today I Learned‍ 🌙 로직을 기능별로 컴포넌트화 하는 것. 기능들을 나누어 각각 독립적인 클래스로 분리. 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 해준다. …
  • Most searched keywords: Whether you are looking for Chapter 1. 컴포넌트 패턴(Component Pattern) – 평생 공부 블로그 : Today I Learned‍ 🌙 로직을 기능별로 컴포넌트화 하는 것. 기능들을 나누어 각각 독립적인 클래스로 분리. 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 해준다. 인프런에 있는 이재환님의 강의 게임 디자인 패턴 with Unity 를 듣고 정리한 필기입니다. 😀
  • Table of Contents:

Skip links

🔔 상속 Vs 컴포넌트

🔔 컴포넌트란

🔔 코드

Chapter 1. 컴포넌트 패턴(Component Pattern) -  평생 공부 블로그 : Today I Learned‍ 🌙
Chapter 1. 컴포넌트 패턴(Component Pattern) – 평생 공부 블로그 : Today I Learned‍ 🌙

Read More

컴포넌트 패턴이란

  • Article author: 1-taek-gameprogramming.tistory.com
  • Reviews from users: 10769 ⭐ Ratings
  • Top rated: 4.3 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 컴포넌트 패턴이란 컴포넌트 패턴을 왜 사용하는가? 게임을 개발하다보면 물리코드 렌더링코드, AI코드 등등을 작성하게되는데, 만약 한 클래스안에 모든 코드들이 섞여 … …
  • Most searched keywords: Whether you are looking for 컴포넌트 패턴이란 컴포넌트 패턴을 왜 사용하는가? 게임을 개발하다보면 물리코드 렌더링코드, AI코드 등등을 작성하게되는데, 만약 한 클래스안에 모든 코드들이 섞여 … 컴포넌트 패턴이란? 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. 라고 책에 적혀있다. 내가 이해한 방식으로 쉽게 풀어서 말해보자면 탈부착이 가능한 클래스라고 설명하고 싶다. 유니티를 사용한..
  • Table of Contents:

태크놀로지

컴포넌트 패턴이란 본문

컴포넌트 패턴이란
컴포넌트 패턴이란

Read More

컴포넌트 패턴 (Componenet Pattern) – 맨텀

  • Article author: mentum.tistory.com
  • Reviews from users: 37622 ⭐ Ratings
  • Top rated: 4.4 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 컴포넌트 패턴 (Componenet Pattern) – 맨텀 로직을 기능별로 모듈화시켜 조합하여 사용하는 것. 도서 ‘게임 프로그래밍 패턴’에서는 디커플링 패턴으로 분류하고 있다. 유니티는 이미 오브젝트에 컴포넌트를 붙이면서 … …
  • Most searched keywords: Whether you are looking for 컴포넌트 패턴 (Componenet Pattern) – 맨텀 로직을 기능별로 모듈화시켜 조합하여 사용하는 것. 도서 ‘게임 프로그래밍 패턴’에서는 디커플링 패턴으로 분류하고 있다. 유니티는 이미 오브젝트에 컴포넌트를 붙이면서 … 로직을 기능별로 모듈화시켜 조합하여 사용하는 것. 도서 ‘게임 프로그래밍 패턴’에서는 디커플링 패턴으로 분류하고 있다. 유니티는 이미 오브젝트에 컴포넌트를 붙이면서 행동을 추가하는 컴포넌트 패턴 방식을..
  • Table of Contents:

컴포넌트 패턴 (Componenet Pattern)

티스토리툴바

컴포넌트 패턴 (Componenet Pattern) - 맨텀
컴포넌트 패턴 (Componenet Pattern) – 맨텀

Read More

컴포넌트 패턴 (Component Pattern)

  • Article author: dhshin94.tistory.com
  • Reviews from users: 49871 ⭐ Ratings
  • Top rated: 4.4 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 컴포넌트 패턴 (Component Pattern) 컴포넌트 패턴 정의. 서로 다른 기능은 나누어 작성하여 서로간 커플링 없이 다룰 수 있게 하는 것. => 로직을 기능별로 컴포넌트화 하는 것. …
  • Most searched keywords: Whether you are looking for 컴포넌트 패턴 (Component Pattern) 컴포넌트 패턴 정의. 서로 다른 기능은 나누어 작성하여 서로간 커플링 없이 다룰 수 있게 하는 것. => 로직을 기능별로 컴포넌트화 하는 것. 1. 컴포넌트 패턴 정의 서로 다른 기능은 나누어 작성하여 서로간 커플링 없이 다룰 수 있게 하는 것 => 로직을 기능별로 컴포넌트화 하는 것 2. 컴포넌트 패턴 사용 이유 using System.Collections; using System..
  • Table of Contents:

태그

관련글

댓글0

공지사항

최근글

인기글

최근댓글

태그

전체 방문자

티스토리툴바

컴포넌트 패턴 (Component Pattern)
컴포넌트 패턴 (Component Pattern)

Read More

13장. 디커플링 – 컴포넌트 패턴 (Component Pattern)

  • Article author: lipcoder.tistory.com
  • Reviews from users: 6231 ⭐ Ratings
  • Top rated: 3.1 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 13장. 디커플링 – 컴포넌트 패턴 (Component Pattern) 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. 플랫포머 게임을 만든다고 해보자. 슈퍼 마리오 게임을 만든다고 하자. …
  • Most searched keywords: Whether you are looking for 13장. 디커플링 – 컴포넌트 패턴 (Component Pattern) 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. 플랫포머 게임을 만든다고 해보자. 슈퍼 마리오 게임을 만든다고 하자. 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. 플랫포머 게임을 만든다고 해보자. 슈퍼 마리오 게임을 만든다고 하자. 그러면 마리오를 대표하는 클래스를 하나 만들어서 여기에 주인공이 게임에서..
  • Table of Contents:

기록공간

13장 디커플링 – 컴포넌트 패턴 (Component Pattern) 본문

13장. 디커플링 - 컴포넌트 패턴 (Component Pattern)
13장. 디커플링 – 컴포넌트 패턴 (Component Pattern)

Read More

Component, 컴포넌트 [디자인패턴](디커플링)**

  • Article author: luv-n-interest.tistory.com
  • Reviews from users: 510 ⭐ Ratings
  • Top rated: 4.6 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about Component, 컴포넌트 [디자인패턴](디커플링)** 이 패턴을 사용하는 의도는 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있도록 한다. 완전 많이 쓰이는 패턴이다. 이것만큼은 잘 해보자. …
  • Most searched keywords: Whether you are looking for Component, 컴포넌트 [디자인패턴](디커플링)** 이 패턴을 사용하는 의도는 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있도록 한다. 완전 많이 쓰이는 패턴이다. 이것만큼은 잘 해보자. 이 패턴을 사용하는 의도는 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있도록 한다. 완전 많이 쓰이는 패턴이다. 이것만큼은 잘 해보자. 플랫포머 게임을 만든다고 해보자. 플레이어 한 명을 정했다면 클래..기술: C++, C#, Unity, Unreal, DX ++ devops k8s
    관심분야: 새로운 컨텐츠를 구현하는게 제일 재밌는 것 이라고 생각하고 있으며 이미 있는 것에 대해 최적화 또는 리팩토링하는데에 관심이 있습니다(엔진 튜닝 또는 커스터마이징) 하지만 개발은 항상 힘이 듭니다. 그래서 포기하고 싶을 때도 많지만 내일 또다시 시도해봅니다.
    요즘엔 새로운 것에 눈을 떴습니다.
  • Table of Contents:

Component 컴포넌트 [디자인패턴](디커플링)

완전 많이 쓰이는 패턴이다

만약 컴포넌트를 쓰지 않는다면 이들 클래스를 어떻게 상속해야 할까

그렇다면 이렇게 유용한 컴포넌트 패턴을 언제 쓸까

그렇다면 기존 클래스는 어떻게 되었을까

이로 얻을 수 있는 것은 무엇일까

티스토리툴바

Component, 컴포넌트 [디자인패턴](디커플링)**
Component, 컴포넌트 [디자인패턴](디커플링)**

Read More

[C++]Component Pattern(컴포넌트 패턴) : 네이버 블로그

  • Article author: blog.naver.com
  • Reviews from users: 47086 ⭐ Ratings
  • Top rated: 4.2 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [C++]Component Pattern(컴포넌트 패턴) : 네이버 블로그 오늘은 간단한 Component Pattern에 대해서 이야기 하고자 합니다. 지금 현재 만들고 있는 엔진을 공부하는 도중 각 클래스 간에 커플링이 생겨서 … …
  • Most searched keywords: Whether you are looking for [C++]Component Pattern(컴포넌트 패턴) : 네이버 블로그 오늘은 간단한 Component Pattern에 대해서 이야기 하고자 합니다. 지금 현재 만들고 있는 엔진을 공부하는 도중 각 클래스 간에 커플링이 생겨서 …
  • Table of Contents:

블로그

악성코드가 포함되어 있는 파일입니다

작성자 이외의 방문자에게는 이용이 제한되었습니다

[C++]Component Pattern(컴포넌트 패턴) : 네이버 블로그
[C++]Component Pattern(컴포넌트 패턴) : 네이버 블로그

Read More

컴포넌트 패턴

  • Article author: tsyang.tistory.com
  • Reviews from users: 35395 ⭐ Ratings
  • Top rated: 4.6 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 컴포넌트 패턴 컴포넌트 패턴. 컴포넌트 패턴은 한 개체가 여러 분야의 코드를 커플링 없이 다룰 수 있게 해준다. 문제. 1. 매 업데이트마다 인풋을 받아서 위치를 … …
  • Most searched keywords: Whether you are looking for 컴포넌트 패턴 컴포넌트 패턴. 컴포넌트 패턴은 한 개체가 여러 분야의 코드를 커플링 없이 다룰 수 있게 해준다. 문제. 1. 매 업데이트마다 인풋을 받아서 위치를 … 컴포넌트 패턴 컴포넌트 패턴은 한 개체가 여러 분야의 코드를 커플링 없이 다룰 수 있게 해준다. 문제 1 매 업데이트마다 인풋을 받아서 위치를 계산하고 바뀐 위치로 스프라이트를 그리는 Player 클래스가 있다..
  • Table of Contents:

컴포넌트 패턴

컴포넌트 패턴

티스토리툴바

컴포넌트 패턴
컴포넌트 패턴

Read More


See more articles in the same category here: Chewathai27.com/to/blog.

C++ 디자인 패턴 13. 컴포넌트 패턴, Component Pattern

컴포넌트 패턴, Component Pattern

한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다.

AI, 물리, 렌더링, 사운드처럼 분야가 다른 코드끼리는 최대한 서로 모르는 게 좋다. 이런 코드를 한 클래스 안에 전부 넣는다면 결과는 뻔하다. 클래스 하나가 5천 줄 넘는 거대한 쓰레기 코드로 뒤덮여버리게 된다. 클래스가 크다는 것은 정말 사소한 걸 바꾸려고 해도 엄청난 작업이 필요할 수 있음을 의미한다. 이런 클래스는 머잖아 기능보다 버그가 더 빨리 늘어나게 된다.

고르디우스의 매듭

코드 길이보다 더 큰 문제가 커플링이다. 여러 게임 시스템이 주인공 캐릭터 클래스 안에서 실타래처럼 얽혀 있다.

if( collidingWithFloor() && (getRenderState() != INVISIBLE) ) { playSound(HIT_FLOOR); }

이 코드를 문제없이 고치려면 물리(collidingWithFloor), 그래픽(getRenderState), 사운드(playSound)를 전부 알아야 한다.

커플링과 코드 길이 문제는 서로 약영향을 미친다. 한 클래스가 너무 많은 분야를 건드리다 보니 모든 프로그래머가 그 클래스를 작업해야 하는데, 클래스가 너무 크다 보니 작업하기가 굉장히 어렵다. 이런 상황이 심해지면 뒤죽박죽이 된 클래스를 손대기 싫어 다른 곳에 땜빵 코드를 넣게 된다.

매듭 끊기

이 문제는 알렉산더 대왕이 고르디우스 매듭을 칼로 끊었던 것처럼 풀 수 있다. 한 덩어리였던 Character 클래스를 분야에 따라 여러 부분으로 나누면 된다. 예를 들어 사용자 입력에 관련된 코드는 InputComponent 클래스에 옮겨둔 뒤에, Character 클래스가 InputComponent 인스턴스를 갖게 한다. Character 클래스가 다루는 나머지 분야에 대해서도 이런 작업을 반복한다.

이러고 나면 컴포넌트들을 묶는 얇은 껍데기 코드 외에는 Character 클래스에 남는 게 거의 없게 된다. 클래스 코드 크기 문제는 클래스를 여러 작은 클래스로 나누는 것만으로 해결했고, 장점은 이뿐만이 아니다.

느슨한 구조

컴포넌트 클래스들은 디커플링되어 있다. PhysicsComponet와 GraphicsComponent는 Character 클래스 안에 들어 있지만 서로에 대해 알지 못한다. 즉 물리 프로그래머는 그래픽 처리는 신경 쓰지 않고 자기 코드를 수정할 수 있다.

사실 컴포너트끼리 상호작용이 필요할 수 있다. 예를 들어 AI 컴포넌트는 캐릭터가 가려는 곳을 물리 컴포넌트를 통해서 알아내야 할 수도 있다. 다만 모든 코드를 한곳에 섞어놓지 않았기 때문에 서로 통신이 필요한 컴포넌트만으로 결합을 제한할 수 있다.

다시 합치기

컴포넌트 패턴의 다른 특징은 이렇게 만든 컴포넌트를 재사용할 수 있다는 점이다. Character 외에도 게임에 필요한 다른 객체들을 생각해보자. 데코레이션(decoration)은 덤불이나 먼지같이 볼 수는 있으나 상호작용은 할 수 없는 객체다. 프랍(prop)은 상자, 바위, 나무같이 볼 수 있으면서 상호작용 할 수 있는 객체다. 존(zone)은 데코레이션과는 반대로 보이지는 않지만 상호작용은 할 수 있는 객체다. 예를 들어 캐릭터가 특정 영역에 들어올 때 컷신을 틀고 싶다면 존을 써먹을 수 있다.

컴포넌트를 쓰지 않는다면 이들 클래스를 어떻게 상속해야 할까? 먼저 이렇게 할 듯하다.

GameObject 클래스에는 위치나 방향 같은 기본 데이터를 둔다. Zone은 GameObject을 상속받은 뒤에 충돌 검사를 추가한다. Decoration도 GameObject를 상속받은 뒤 렌더링 기능을 추가한다. Prop은 충돌 검사 기능을 재사용하기 위해 Zone을 상속받는다. 하지만 Prop이 렌더링 코드를 재사용하기 위해 Decoration 클래스를 상속하려는 순간 ‘죽음의 다이아몬드’라고 불리는 다중 상속 문제가 생낀다.

컴포넌트로 만들어보자. 상속은 전혀 필요가 없다. GameObject 클래스 하나와 PhysicsComponent, GraphicsComponent 클래스 두 개만 있으면 된다. 데코레이션은 GraphicsComponent는 있고 PhysicsComponent는 없는 GameObject다. 프랍에는 둘 다 있다. 여기에느 코드 중복도, 다중 상속도 없다. 클래스 개수도 네 개에서 세 개로 줄였따.

컴포넌트는 기본적으로 객체를 위한 플러그 앤 플레이라고 볼 수 있다. 개체 소켓에 재사용 가능한 여러 컴포넌트 객체를 꽂아 넣음으로써 복잡하면서도 기능이 풍부한 개체를 만들 수 있다.

패턴

여러 분야를 다루는 하나의 개체가 있다. 분야별로 격리하기 위해, 각각의 코드를 별도의 컴포넌트 클래스에 둔다. 이제 개체 클래스는 단순히 이들 컴포넌트들의 컨테이너 역할만 한다.

언제 쓸 것인가?

한 클래스에서 여러 분야를 건드리고 있어서, 이들을 서로 디커플링하고 싶다.

클래스가 거대해져서 작업하기가 어렵다.

여러 다른 기능을 공유하는 다양한 객체를 정의하고 싶다. 단 상속으로는 딱 원하는 부분만 골라서 재사용할 수가 없다.

예제 코드

통짜 클래스

컴포넌트 패턴을 어떻게 적용할지를 더 명확하게 알 수 있도록, 먼저 컴포넌트 패턴을 아직 전용하지 않아 모든 기능이 통짜 클래스에 다 들어 있는 Character 클래스부터 보자.

class Character { public: Character: velocity_(0), x_(0), y_(0) {} void update(World& world, Graphics& graphics); private: static const int WALK_ACCELERATION = 1; int velocity_; int x_, y_; Volume volume_; Sprite spriteStand_; Sprite sprriteWalkLeft_; Sprite spriteWalkRight_; };

Character 클래스의 update 메서드는 매 프레임마다 호출된다.

void Character::update(World& world, Graphics& graphics) { // 입력에 따라 주인공의 속도를 조절한다. switch(Controller::getJoystickDirection()) { case DIR_LEFT: velocity_ -= WALK_ACCELERATION; break; case DIR_RIGHT: velocity_ += WALK_ACCELERATION; break; } // 속도에 따라 위치를 바꾼다. x_ += velocity_; world.resolveCollision(volume_, x_, y_, velocity_); // 알만은 스프라이트를 그린다. Sprite* sprite = &spriteStand_; if(velocity_ < 0) { sprite = &spriteWalkLeft_; } else if(velocity_ > 0) { sprite = &spriteWalkRight_; } graphics.draw(*sprite, x_, y_); }

위 코드는 입력에 따라 주인공을 가속한다. 다음으로 물리 엔진을 통해 주인공의 다음 위치를 구한다. 마지막으로 화면에 캐릭터를 그린다.

구현은 굉장히 간단하다. 중력도 없고 애니메이션도 없는등 여러 상세한 구현이 다 빠져 있다. 그럼에도 코드를 보면 update 함수 하나를 여러 분야의 프로그래머가 작업해야 하고 코드가 더러워지기 시작했다는 것을 알 수 있다. 이런 코드가 몇천 줄이 넘어가면 얼마나 괴로울지 짐작이 간다.

분야별로 나누기

먼저 분야 하나를 정해서 관련 코드를 Character에서 별도의 컴포넌트 클래스로 옮긴다. 가장 먼저 처리되는 입력 분야부터 시작한다. Character 클래스가 처음 하는 일은 사용자 입력에 따라 주인공의 속도를 조절하는 처리다. 그에 해당하는 로직을 별개의 클래스로 옮겨보자.

class InputComponent { public: void update(Character& character) { switch(Controller::getJoystickDirection()) { case DIR_LEFT: character.velocity_ -= WALK_ACCELERATION; break; case DIR_RIGHT: character.velocity_ += WALK_ACCELERATION; break; } } private: static const int WALK_ACCELERATION = 1; };

어려울 거 없다. Character 클래스의 update 메서드에서 앞부분을 InputComponent 클래스로 옮겼다.

class Character { public: int velocity; int x, y; void update(World& world, Graphics& graphics) { input_.update(*this); // 속도에 따라 위치를 바꾼다. x += velocity; world.resolveCollision(volume_, x, y, velocity); // 알만은 스프라이트를 그린다. Sprite* sprite = &spriteStand_; if(velocity < 0) { sprite = &spriteWalkLeft_; } else if(velocity > 0) { sprite = &spriteWalkRight_; } graphics.draw(*sprite, x, y); } private: InputComponent input_; Volume volume_; Sprite spriteStand_; Sprite sprriteWalkLeft_; Sprite spriteWalkRight_; };

Character 클래스에 InputComponent 객체가 추가되었다. 이전에는 사용자 입력을 update() 에서 직접 처리했찌만, 지금은 입력 컴포넌트에 위임한다.

input_.update(*this);

이제 시작일 뿐인데도 벌써 Character 클래스가 더 이상 Controller를 참조하지 않도록 커플링을 일부 제거했다.

나머지도 나누기

이제 남아 있는 물리 코드와 그래픽스 코드도 같은 식으로 복사 & 붙여넣기를 한다. PhysicsComponent부터 보자.

class PhysicsComponent { public: void update(Character& character, World& world) { character.x += character.velocity; world.resolveCollision(volume_, character.x, character.y, character.velocity); } private: Volume volume_; };

물리 코드를 옮기고 보니 몰리 데이터도 같이 옮겨졌다. 이제 Volume 객체는 Player가 아닌 PhysicsComponent에서 관리한다.

마지막으로 렌더링 코드를 옮긴다.

class GraphicsComponent { public: void update(Character& character, Graphics& graphics) { Sprite* sprite = &spriteStand_; if(character.velocity < 0) { sprite = &spriteWalkLeft_; } else if(character.velocity > 0) { sprite = &spriteWalkRight_; } graphics.draw(*sprite, character.x, character.y); } private: Sprite spriteStand_; Sprite spriteWalkLeft_; Sprite spriteWalkRight_; };

Character 클래스에서 거의 모든 코드를 뽑아냈다. Character 클래스에는 코드가 거의 남아있지 않다.

class Character { public: int velocity; int x, y; void update(World& world, Graphics& graphics) { input_.update(*this); physics_.update(*this, world); graphics_.update(*this, graphics); } private: InputComponent input_; PhysicsComponent physics_; GraphcisComponent graphics_; };

이렇게 바뀐 Character 클래스는 두 가지 역할을 한다. 먼저 자신을 정의하는 컴포넌트 집합을 관리하고 컴포넌트들이 공유하는 상태를 들고 있는 역할이다. 위치(x, y)와 속도(velocity) 값을 Character 클래스에 남겨놓은 이유는 두 가지다. 먼저, 이들 상태는 ‘전 분야’에서 사용된다. 컴포넌트로 옮기고 싶어도 거의 모든 컴포넌트에서 이 값을 사용하다 보니 어느 컴포넌트에 둘지 애매하다.

그보다 더 중요한 이유는 이렇게 하면 컴포넌트들이 서로 커플링 되지 않고도 쉽게 통신할 수 있기 때문이다.

오토-캐릭터

동작 코드를 별도의 컴포넌트 클래스로 옮겼지만 아직 추상화하지 않았따. Character 클래스는 자신의 동작을 어떤 구체 클래스에서 정의하는지를 정확하게 알고 있다. 이걸 바꿔보자.

사용자 입력 처리 컴포넌트를 인터페이스 뒤로 숨기려고 한다. InputComponent을 다음과 같이 추상 상위 클래스로 바꿔보자.

class InputComponent { public: virtual ~InputComponent() {} virtual void update(Character& character = 0); };

사용자 입력을 처리하던 코드는 InputComponent 인터페이스를 구현하는 클래스로 끌어내린다.

class PlayerInputComponent : public InputComponent { public: virtual void update(Character& character) { switch(Controller::getJoystickDirection()) { case DIR_LEFT: character.velocity -= WALK_ACCELERATION; break; case DIR_RIGHT: character.velocity += WALK_ACCELERATION; break; } } private: static const int WALK_ACCELERATION = 1; };

Character 클래스는 InputComponent 구체 클래스의 인스턴스가 아닌 인터페이스의 포인터를 들고 있게 바꾼다.

class Character { public: int velocity; int x, y; Character(InputComponent* input) : input_(input) {} void update(World& world, Graphics& graphics) { input_->update(*this); physics_.update(*this, world); graphics_.update(*this, graphics); } private: InputComponent* input_; PhysicsComponent physics_; GraphicsComponent graphics_; };

이제는 Character 객체를 생성할 때, Character이 사용할 입력 컴포넌트를 다음과 같이 전달할 수 있다.

Character* character = new Character(new PlayerInputComponent());

어떤 클래스라도 InputComponent 추상 인터페이스만 구현하면 입력 컴포넌트가 될 수 있다. update() 는 가상 메서드로 바뀌면서 속도는 조금 느려졌다.

그러나 ‘데모 모드’에서 플레이어가 아무것도 안하고 가만히 앉아 있을 때, 대신 컴퓨터가 자동으로 게임을 플레이 하는등의 기능을 만들 수 있다.

입력 컴포넌트 클래스를 인터페이스 밑에 숨긴 덕분에 이런 걸 만들 수 잇게 되었다. PlayerInputComponent는 실제로 게임을 플레이할 때 사용하는 클래스이니, 다른 클래스를 만들어보자.

class DemoInputComponent : public InputComponent { public: virtual void update(Character& character) { // AI가 알아서 Character을 조정한다… } };

데모 모드용으로 캐릭터 객체를 생성할 때에는 새로 만든 컴포넌트를 연결한다.

Character* character = new Character(new DemoInputComponent());

More

유니티 프레임워크의 핵심 클래스인 GameObject는 전적으로 컴포넌트 방식으로 맟춰 설계되었다.

XNA 게임 프레임워크에는 Game이라는 핵심 클래스가 있는데, 여기에는 GameComponent 객체 컬렉션이 들어 있다.

이 포스트의 글과 그림의 출처는 http://gameprogrammingpatterns.com/component.html 입니다.

by 소년코딩

추천은 글쓴이에게 큰 도움이 됩니다.

악플보다 무서운 무플, 댓글은 블로그 운영에 큰 힘이됩니다.

Chapter 1. 컴포넌트 패턴(Component Pattern)

인프런에 있는 이재환님의 강의 게임 디자인 패턴 with Unity 를 듣고 정리한 필기입니다. 😀

Chapter 1. Component Pattern

🔔 상속 Vs. 컴포넌트

상속 : A is B

장점 부모 클래스로부터 물려받은 부분은 다시 쓸 필요가 없기 때문에 재사용 면에 있어서 효율적이다.

단점 부모, 조상 클래스가 될 공통된 최소 필수 집합을 개발자가 미리 예상하기가 힘들다. 즉, 완벽하게 순수한 Base Class를 만드는 것은 힘듬 자식 클래스가 필요로 하지 않는 기능도 물려줄 수 있는 등등 +, – 해야할게 너무 많다. 컴포넌트들끼리 커플링이 심하다. A 를 삭제하면 A 를 상속 받고 있던 B, C 에 치명적인 문제가 생긴다. A 의 부분을 상당수 재사용하고 있었는데 A 가 없어졌으니까!

오크는 몬스터다. Orc is a monster. Is-A 관계이므로 오크는 몬스터를 상속 받아 만들어야 함.

monster.

컴포넌트 : A has B

빈 컨테이너에 필요할 때마다 원하는 기능을 갖다 붙여 포함시키는 방식. 부품

각자의 기능을 가지고 있는 스스로 동작하는 독립적인 부품 애니메이션만 관련있는 컴포넌트, 물리 기능만 관련있는 컴포넌트, 이동 시키는 컴포넌트 등등 각자 기능을 담당하는 컴포넌트들이 독립적으로 구현이 되어 있다. 독립적인 클래스로 만들어 두고, 만들어 둔 것을 부품 붙이듯이 갖다 붙이며 됨. 컴포넌트를 뗀다고 해서 오브젝트의 다른 컴포넌트에 영향이 가는 것은 없음. 가장 큰 장점! 서로 영향 가는게 없다. 컴포넌트들끼리 독립적이며 커플링이 없다. 부품을 갈아끼면 그만. +, – 가 쉽다.

코드의 의존성을 줄이고 재활용성을 높인다.

플레이어는 인벤토리 기능을 가진다. Player has a inventory. 인벤토리 기능은 컴포넌트로 구현하는 것이 좋다.

inventory.

🔔 컴포넌트란

로직을 기능별로 컴포넌트화 하는 것. 기능들을 나누어 각각 독립적인 클래스 로 분리.

한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 해준다. 컴포넌트만 수정하면 되서 요구사항에 대한 대처가 빨라 유지보수시 편하다.

유니티는 컴포넌트 구조를 사용하고 있다.

캡슐화를 더 살려 준다.

🔔 코드

컴포넌트 패턴을 사용하지 않았을 때

한 코드 내에서 오브젝트를 90도 회전시키고 오브젝트를 이동시키고 0.5초 yield 기다리는

위와 같은 세가지 일련의 과정을 가진 코루틴 함수가 있다고 해보자.

한 코드 내에서 회전도 하고 이동도 하고 있지만 만약에 회전을 다하고나면 0.3초 기다리고 이동은 0.5초 기다리도록 수정해야 한다면 코드 상당수를 수정해야 한다.

📜SpaghetticAct.cs

using System.Collections ; using System.Collections.Generic ; using UnityEngine ; enum MOVE { MOVE_RIGHT , MOVE_LEFT } public class SpaghettiAct : MonoBehaviour { GameObject player1 ; GameObject player2 ; MOVE move = MOVE . MOVE_RIGHT ; void Start () { player1 = GameObject . Find ( “Player1” ) as GameObject ; player2 = GameObject . Find ( “Player2” ) as GameObject ; StartCoroutine ( “MixedAct” ); } // 0.5초마다 객체들을 회전하면서 (글로벌 방향으로) 이동시키기 IEnumerator MixedAct () { while ( true ) { player1 . transform . Rotate ( 90.0f * Vector3 . up ); player2 . transform . Rotate ( 90.0f * Vector3 . up ); if ( player1 . transform . position . x < - 4 ) { move = MOVE . MOVE_RIGHT ; } else if ( player1 . transform . position . x > 4 ) { move = MOVE . MOVE_LEFT ; } if ( move == MOVE . MOVE_RIGHT ) { player1 . transform . Translate ( 1.0f * Vector3 . right , Space . World ); player2 . transform . Translate (- 1.0f * Vector3 . right , Space . World ); } else { player1 . transform . Translate (- 1.0f * Vector3 . right , Space . World ); player2 . transform . Translate ( 1.0f * Vector3 . right , Space . World ); } yield return new WaitForSeconds ( 0.5f ); } } }

컴포넌트 패턴을 사용했을 때

기능 별로 나누어 클래스로 묶어 독립적으로 분리해놓고 필요할 대 가져다 쓴다.

이동과 회전 기능을 클래스로 따로 묶어 분리하였다. 📜Movs.cs : 이동에 관한 것만 묶어 작성. 0.3초 기다리는 코루틴 함수 有. 📜Rotate.cs : 회전에 관한 것만 묶어 작성. 0.5초 기다리는 코루틴 함수 有.

이제 유지보수시 한 컴포넌트에 대한 부분만 수정하면 되서 편해진다. 두 컴포넌트(C#스크립트)의 커플링이 없어졌기 때문이다.

📜Move.cs

using System.Collections ; using System.Collections.Generic ; using UnityEngine ; enum MOVE2 { MOVE_RIGHT , MOVE_LEFT } public class MoveAct : MonoBehaviour { MOVE2 move = MOVE2 . MOVE_RIGHT ; void Start () { StartCoroutine ( “Move” ); } // 0.5초마다 (글로벌 방향으로) 이동시키기 IEnumerator Move () { while ( true ) { if ( transform . position . x < - 4 ) { move = MOVE2 . MOVE_RIGHT ; } else if ( transform . position . x > 4 ) { move = MOVE2 . MOVE_LEFT ; } if ( move == MOVE2 . MOVE_RIGHT ) { transform . Translate ( 1.0f * Vector3 . right , Space . World ); } else { transform . Translate (- 1.0f * Vector3 . right , Space . World ); } yield return new WaitForSeconds ( 0.5f ); } } }

📜Rotate.cs

using System.Collections ; using System.Collections.Generic ; using UnityEngine ; public class RotateAct : MonoBehaviour { void Start () { StartCoroutine ( “Rotate” ); } // 0.5초마다 객체 회전시키기 IEnumerator Rotate () { while ( true ) { transform . Rotate ( 90.0f * Vector3 . up ); yield return new WaitForSeconds ( 0.3f ); } } }

🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

컴포넌트 패턴이란

컴포넌트 패턴이란?

한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다. 라고 책에 적혀있다. 내가 이해한 방식으로 쉽게 풀어서 말해보자면 탈부착이 가능한 클래스라고 설명하고 싶다. 유니티를 사용한 분이 계신다면 컴포넌트에 개념을 더 쉽게 이해할수 있을거다.

컴포넌트 패턴을 왜 사용하는가?

게임을 개발하다보면 물리코드 렌더링코드, AI코드 등등을 작성하게되는데, 만약 한 클래스안에 모든 코드들이 섞여있다면 정말 끔찍할것이다. 또한 협업에 있어서 개발속도가 늦춰지고 디버깅에 많은 어려움을 겪게된다. 이러한 상황을 피하기 위해 분야별로 담당하는 파트를 나눠 설계해야 할 필요가 있다.

컴포넌트 패턴의 특성1 – 분야 나누기

게임 캐릭터는 조작을 담당하는 파트, 애니메이션을 담당하는 상태머신 컨트롤러, 캐릭터의 월드행렬을 갖고 있는 물리파트등이 존재한다. 위와 같이 구현되는 게임의 분야를 나눠보자.

컴포넌트 패턴의 특성2 – 각각 독자적인 컴포넌트들

각 컴포넌트 클래스들은 서로에 대해 알지 못하는것이 중요하다. 애니메이션을 담당하는 상태머신 컨트롤러에서 캐릭터의 위치를 바꿔버리는 상황은 매우 끔찍하다.

하지만 현실적으로 컴포넌트들끼리 서로의 정보를 알아야할상황이 많이 발생한다. A.I 컴포넌트에서는 물리컴포넌트의 월드행렬에 대해 알아야한다. 이때 다른 대상을 통해 그 정보를 알수있는 방법도 있고 이를 해결하는 방법은 매우 다양하다.

컴포넌트 패턴 언제 쓸것인가?

한 클래스에서 여러분야를 건드리고 있어, 이들을 서로 디커플링하고 싶다.

클래스가 거대해져서 작업하기 어렵다.

여러 다른 기능을 공유하는 다양한 객체를 정의하고 싶다. 단 상속으로는 딱 원하는 부분만 골라서 재사용할수가 없다.

주의사항

사실 컴포넌트 패턴에서 가장 어려운 부분은 컴포넌트끼리 통신하는 부분이라 생각한다. 또한 컴포넌트들을 어디에 두어 관리할것인지도 복잡하다.

[실습] 게임오브젝트와 컴포넌트 인터페이스를 설계하고, 서로 통신하는 원리를 이해하자.

컴포넌트 인터페이스 설계

class GameObject; class Component { protected: string m_Name; GameObject* m_Owner; public: void SetOwner(GameObject* obj); GameObject* GetOwner() const; string GetName() const; public: virtual void Awake() {}; virtual void Update() {}; public: Component(string compName); virtual ~Component(void); };

추상클래스 Awake, Update 함수가 존재하고, 자신이 누구한테 소유되어있는지를 알수있는 컴포넌트 소유자의 포인터를 저장합니다.

게임오브젝트 인터페이스 설계

class Component; class GameObject { protected: string m_Name; map m_Components; public: void AddComponent(Component* pComponent); template tComp* GetComponent(const string componentName) { if (!m_Components.count(componentName)) return nullptr; return dynamic_cast(m_Components.at(componentName)); } public: virtual void Awake() {}; virtual void Update() {}; virtual void Render() {}; public: GameObject(string name); virtual ~GameObject(); };

void GameObject::AddComponent(Component* pComponent) { if (m_Components.count(pComponent->GetName())) return; pComponent->SetOwner(this); m_Components.emplace(pComponent->GetName(), pComponent); }

게임오브젝트가 컴포넌트를 추가하면 컴포넌트의 이름과, 주소를 저장합니다. 객체를 통해 컴포넌트를 찾기 위해 검색이 빠른 map을 사용하였습니다. 컴포넌트를 추가할때 게임오브젝트 자신의 주소를 컴포넌트에 지정해줍니다. (SetOwner)

오브젝트와 컴포넌트를 생성하주는 메서드 기능 제공

namespace ObjectFactory { template tGameObject* CreateObject(string objName) { tGameObject* obj = new tGameObject(objName); obj->Awake(); return obj; } template tComponent* CreateComponent(string compName) { tComponent* comp = new tComponent(compName); comp->Awake(); return comp; } }

게임오브젝트나 컴포넌트가 맨처음 생성될때 Awake함수를 한번 호출합니다. 이외에 상속을 받는 자식객체들을 생성해주는 유틸함수를 제공해주어야하기때문에 namespace로 분류하였습니다. 혹은 가변템플릿인자로도 구현이 가능해보입니다.

제작된 컴포넌트 사용방법

vector m_GameObjects; vector m_Components; class Camera : public Component { public: virtual void Awake() { cout << "Awake Camera" << endl; }; virtual void Update() { cout << "Update Camera" << endl; //m_Owner->GetComponent ,,, 객체내의 다른 컴포넌트와 통신 }; public: Camera(string name) : Component(name) {} }; int main(void) { // Init GameObject* player1 = ObjectFactory::CreateObject(“player1”); m_GameObjects.push_back(player1); Camera* comp1 = ObjectFactory::CreateComponent(“camera1”); m_Components.push_back(comp1); // Running while(true) { player1->AddComponent(comp1); Camera* player1Camera = player1->GetComponent(“camera1”); for (auto& p : m_GameObjects) { p->Update(); p->Render(); } } return 0; }

카메라를 컴포넌트로 만들어서 플레이어1에 추가해보았습니다. ObjectFactory를 사용하여 컴포넌트를 생성하고 객체를 통해 컴포넌트를 얻을 수 있습니다.

※ 컴포넌트가 자신을 소유한 객체의 주소를 알고있기 때문에 객체의 다른 컴포넌트와도 통신이 가능합니다.

컴포넌트 패턴을 구현할때 주의해야할점

필자는 모든객체와 컴포넌트들을 vector로 따로 한번더 관리하고 있다. 만약 게임오브젝트가 사라지면 게임오브젝트가 소유하고 있는 컴포넌트들에 접근할 방법이 사라진다. 이는 게임오브젝트가 사라질때 소유한 컴포넌트들을 모두 삭제하는 방법도 존재한다. 이부분은 컴포넌트 패턴을 사용하며 가장 어려움을 겪었던 부분이다.

객체의 생성과 해제를 관리하는 오브젝트풀에 대해선 많은 고민과 디자인패턴들을 연구하고 고민해보아야한다.

출처

도서, 게임프로그래밍 패턴, 한빛미디어

So you have finished reading the 컴포넌트 패턴 topic article, if you find this article useful, please share it. Thank you very much. See more: 컴포넌트 패턴 예제, C++ 컴포넌트 패턴, 리액트 컴포넌트 패턴, 커맨드 패턴, 프론트엔드 컴포넌트 디자인 패턴, 디자인 패턴, 옵저버 패턴, 게임 전략 패턴

Leave a Comment