2010년 3월 18일 목요일

엔진들 엔진들,,,


요즘 유니티 3D 가 멋지게 떠오르면서,,,
GDC2010 내용들을 보니 주 화제인듯 합니다.

이걸 보면서 게임 엔진 시장은 완전히 재편된 거 같은데요.

고가 엔진 시장(퀄리티를 중심으로 무수한 사람과 인력을 쏟는,,,) : 언리얼/크라이 가,,,
=>이쪽은 TD 의 역할이 매우 크므로,,,프로그래밍 디자인 모두 센스 있는 인재가 많이 필요해보입니다.

중가? MMO 처럼 소스 코드를 많이 고쳐야 하는 쪽은 : 게임브리오/비젼,,,,
=>이쪽은 아직 엔진 프로그래머들이 열심히 렌더러도 고치고,
=> 새로운 미들웨어를 붙여보기도 하는,,재미난 곳,!!ㅎ

그리고
저가/무료 : 유니티3D, Shiva3D(이건 그냥 잘 모르겠음-_-)
원래는 자체 엔진은 개발하던 미니 게임(서양에서는 캐쥬얼 게임이라고 부르는 플레이타임 5분 정도의 게임들,,,)이나 스마트폰 게임들은,,,,거의 여기로 가는게 아닐까 싶네요.
=>이쪽은 프로그래머가 급격히 필요없어지는 느낌입니다.
=>프로그래머 대신 스크립터가 필요한듯,,,(뭐 액션스크립트를 프로그래머가 하듯이 이것도 프로그래머가 하겠지만!!0

저는 개인적으로 게임브리오나 비젼처럼 엔진도 이것저것 건드리고,
미들웨어도 붙여보고 이런쪽이 재밌긴 한데요.
(이쪽이 MMO 에 제일 맞는 거 같기도 하고요,,,개인적인 생각입니다만,,,)

유니티3D 쪽도 돌아가는 건 파악해야 되겠다는 생각이 드네요.
(주변에서 이걸로 뭘해보자고 많이들 하시는데-_-아아 저도 뭔가 해보고 싶긴 한데. 게을러서,,,)

2010년 3월 16일 화요일

게임 산업의 미래.

요즘 여러 사람들과 얘기하면서,
게임 산업은 어떨지 그리고 프로그래머의 미래는 어떨지 궁금해 지곤 합니다.

1. 스마트 폰, SNS 등으로 인한 캐쥬얼 게임의 폭발!!!
여기에는 Unity3D 나 Shiva3D 같은 안정적이고 빠르게 만들 수 있는 게임플랫폼 덕분도 있는듯!~
페이스북 게임도 많이들 하져~~

2. 거대 자본이 들어가야 하는 AAA 온라인게임?
거대 자본과 체계화된 시스템이 필요한 거대 온라인 게임은 블리자드사가 거의,,,
주변 개발사도 보면 뛰어나고 우수한 인재들은 많은데, 뭔가 체계화되고 관리된 시스템이 없어서,
무너지는 것처럼 보이는 경우가 많습니다. (적절한 PM 의 부재랄까요,,,-_-)

3. 프로그래머?엔진?
소규모 인디팀에서 자체 엔진으로 개발하는 경우가 많이 사라진듯 합니다.
자체 엔진의 경우 안정성이나 문서화 등이 쉽지 않아서, 개발자 한명 한명이 소중했는데 말이져~~
아무튼 그래서
대규모 - 언리얼,크라이
중간규모 - 게임브리오, 비젼,,,등
소규모 - 유니티

저렇게 규모별로 맞는 엔진이 존재하는 듯 합니다. (물론 게임 타입에 따라 다르겠지만요)
소규모 팀에서 사실 선택할 수 있는 옵션이 많다는 건 좋은 거 같기도 합니다.
예전처럼 오픈소스 엔진위의 자체 엔진 이런 형태는 많이 사라지지 않을까 생각합니다.
결국 이렇게 되면 엔진하시던 분들은 전문화 되어 미들웨어사나 엔진사를 차리거나 그런 회사로 들어가게 될 거 같네요.
(아니면 중간규모 급에서는 엔진 수정이 많으니 그쪽 엔진에 필요 기능 추가도 있을 수 있겠네요)

아무튼 게임 시장은 커질거라고 생각합니다.
(다들 스마트폰-게임기를 한대씩 들고 다닐테니까요,,,)

하지만 늘어나는 만큼 순수 프로그래머들이 많이 필요하진 않을 거 같네요,
예전 게임처럼 대규모로 프로그래머들이 우르르 일하는 경우도 적어지지 않을까 싶고요.

그리고 점점 엔지니어보다는 어느 정도 아트 감각을 가지고,
TD 로 활동하는 분들이 많아지지 않을까 싶습니다.

UDK(언리얼) 나 유니티를 써보면 어느 정도 툴 사용 감각있는 개발자가 확실히 유리하는 생각이 들거든요.

아무튼 결론은 ,,, 이것저것 할께 많아지네요. 늘 그래왔듯이...
요새 디자이너 분들도 스크립트 공부 많이 하시던데,
우리도 툴 공부 열심히 해야 될 듯 합니다.!!



2010년 3월 15일 월요일

컴포넌트 시스템 정리 - 1

안녕하세요. 게임 프로그래밍은 기획자와 디자이너를 위한 서비스라고 생각하는 harry입니다. 요즘 온라인 게임이 유행하고 또 대형화 되면서 게임 개발 이후에 유지 보수 및 패치의 중요성이 대두 되고 있습니다. 그럼 쉽고 가볍게 패치를 하기 위해서는 게임 코딩에 어떤 걸 고려해야 할까요.
우선 컨텐츠로 인한 코드가 증가하여도 전체 클라이언트 어플리케이션 내의 복잡도가 증가하지 않아야 합니다. 그러나 이는 전통적인 오브젝트 - 오리엔트 프로그래밍에서는 쉽지 않습니다. 새 객체 추가 요청을 받았는데 기존과 어느 정도 비슷합니다. 그럼 기존 코드를 상속받아 새로운 코드를 작성합니다. 그러나 완전히 똑같질 않고 제거해야 되는 부분도 있습니다. 상속이므로 이미 사용되고 있는 기존 코드의 내용을 제거하기는 어렵습니다. 오버라이딩을 하게 됩니다.
그럼 컴포넌트 방식은 어떻게 될까요?
새롭게 추가 되는 내용을 머리 구상합니다. 이를 하나의 기능단위로 클래스로 만듭니다. 이 클래스는 상속으로 부터라기보다는 기본 컴포넌트 인터페이스로 부터 받습니다. 그리고 이 기능은 객체에 추가 됩니다.

쉽게 보면.
Human 라는 클래스가 있고,
여기에 CTransform(Translation,Rotation,Scale) 등의 정보를 갖는 클래스가 있습니다.

Human
  CTransform m_transform
  CAnimation m_animation

이러한 형태가 됩니다.

그러나 그냥 이렇게 코드를 짜게 되면
클래스가 늘어나게 되면 Entity 클래스가 복잡해지게 되고,

서로 다른 작동을 하는 사람 Entity와 나무 Entity는 각각 따로 클래스를 만들어야 됩니다.

그럼 어떻게 하면 될까요? 어떻게 하면 공통된 인터페이스로 처리할 수 있을까요?

Entity
  List<ComponentInterface*> m_componentList

ComponentInterface는 상속 받아서 CTransform,CAnimation 등의 컴포넌트를 가질 수 있습니다.

그럼 이렇게 했을 때는 기존의 경우와 비교해서 어떤 문제가 생길까요?

CAnimation은 캐릭터를 애니메이션 하기 위해서 Transform 정보가 필요합니다.

즉 CHuman::Update()
에서는 m_animation.Update(m_transform)
과 같이 m_animation 에 transform을 알려줄 필요가 생깁니다.

그럼 Entity 의 List 구조는 위와 같은 형태를 어떻게 해결할까요?
Entity 클래스는 리스트만 담고 있을 분 어떤 것들을 가지고 있는지 스스로 알 수 없습니다.

이런 경우에는

ComponentInterface 클래스에 다른 컴포넌트의 변수를 가지고 올 수 있는 인터페이스가 필요합니다.

보통 컴포넌트 간에 주고 받아야 하거나, 세이브/로드가 필요한 데이타의 경우 Property라고 부릅니다.
이 Property들을 주고 받으려면 인터페이스가 필요하게 됩니다.

즉 ReadProperty(Translate,&Vector3),ReadProperty(Rotation,&Vector3),ReadProperty(Scale,&Vector3)
과 같은 형태로 Transform을 읽어올 수 있도록 인터페이스를 만들 수 있습니다.

Entity
 ReadProperty(String,&Vector3)
    이 함수는 내부적으로 모든 프로퍼티를 돌면서 String에 해당하는 Property의 밸류를 찾아서 리턴 해줍니다.

물론 다른 컴포넌트의 값을 찾기 위해 String을 쓴다면, 프레임 저하가 생길것으로 예상됩니다.
스트링 비교는 매 프레임마다 하기에는 부하가 큰 연산입니다.
이럴 경우 스트링을 관리하는 클래스를 만들고,
String을 전체 테이블로 관리하게 하고 같은 이름의 스트링은 레퍼런스로 처리하면 됩니다.
같은 스트링의 경우는 같은  메모리 주소를 갖게 되므로 단순 비교로 처리할 수 있습니다.
C#의 StringBuilder등을 참조하세요.

그럼 Component Interface 를 어떻게 해야 할지 알아볼까요.
위에서 보았던 CTransform을 컴포넌트로 구성해 봅시다.
우선 ReadProperty 라는 함수가 필요합니다.
ReadProperty(string name,Point3& pt3)
 if(name == RotationString)
   pt3 = m_rotation;
 else if(name == ScaleString)
   pt3 = m_scale;

위와 같이 변수를 이름과 매핑 시켜서 가져옵니다. 상황에 따라서는 Map을 사용해서 빠르게 접근할 수 있도록 만들수 있습니다.

그럼 SetProperty 도 위와 같이 구성할 수 있습니다.
if...
else....

다른 컴포넌트에서 Entity의 ReadProperty를 호출하게 되면 모든 컴포넌트를 돌면서 해당하는
Property를 가지고 오게 됩니다.

그럼 다시 돌아가서 공통의 인터페이스를 가지는 컴포넌트를 만들어서
속성을 관리할 경우 어떤 이점이 있을까요?
우선 속성의 추가/삭제가 쉬워집니다.

게임을 개발하다 보면 기획에서 캐릭터가 새처럼 날게 해줘라고 어느날 갑자기 말합니다.
그래서 날기 기능을 열심히 기존 코드의 Update함수를 수정하여 넣습니다.
그리고 어느 날 아 나는 건 우리 게임에 어울리지 않고 유저들이 사용하지 않으니 빼달라고 합니다.

이미 기능을 추가한지 한참이 지났고 롤백으로 기능을 제거 할 수 없습니다. 이 경우 하나하나 찾아서 빼거나 최악의 경우
게으름을 이유로 호출하는 부분말 살짝 지웁니다.
Legacy 코드가 증가하게 되고, 결국 코드는 점점 방대해집니다.

그리고 컴포넌트로 했을 경우에는 어떨까요?
새처럼 날 수 있게 하는 FlyComponent가 추가 됩니다.
Entity의 ComponentList 에 추가 되겠지요.
그리고 어느 날 빼달라고 하면 그저 리스트에서 제거 됩니다.

그리고 두번째 장점은 직렬화-Serialization이 쉽게 가능해집니다.
스트링으로 매피되는 프로퍼티들을 처음에 추가 해주고,
GetProperty로 모두 얻어와 하나하나 저장할 수 있겠지요.

물론 이게 가능하려면 타입에 대한 어느 정도 구조화가 필요합니다.
즉 게임에서라면 자주 쓰이는 데이타인
INT,FLOAT,POINT3,MATRIX 등등의 기본 데이터가 있을테고,
이런 기본적인 데이타에 대해서는 어떻게 저장할지 미리 규칙을 정해둡니다.

그리고 이후 프로퍼티들은 위 규칙에 따라 매핑되는 이름으로 저장하게 됩니다.