NDC11_슈퍼클래스

6,006 views

Published on

Superclass Based Game Object System

NDC11_슈퍼클래스

  1. 1. 슈퍼 클래스 :단순함을 유지하여 개발생산성 향상시키기Super-class based game object system ㈜소프트네트 김성익 noerror@softnette.com
  2. 2. 목차01. 지향점02. 개발 관점의 변화 추적03. 슈퍼클래스 소개04. 슈퍼클래스 기반 게임 오브젝트 시스템05. 기타 사례 및 아이디어06. 결론07. Q&A
  3. 3. 지향점1. 납득 가능한 기획적 명세는 가능한 모두 구현하자생산성, 확장성, 재사용성2. 빠르게 개발하되 코드의 품질을 일정 수준 이상으로 유지하자단순화, 표준화 성능, 우아함솔루션 : 개발 역량을 높이거나 더 오래 일을 하거나 ??
  4. 4. 개발 관점의 변화 추적절차적에서 객체지향적으로 일반화된 효과적이고 유연하며, 확장성 높은 개발 추상화, 상속 fread(header, 1, len, fp); f->Read(&header, len); CreateTextureFromMemory(ptr, size, pTexture); CreateTextureFromFile(fp, &pTexture); CFileIO* f1 = CMemIO::Create(ptr, size); CreateTextureFromFile(f1, &pTexture); CFileIO* f2 = CStdIO::Open(L"checkbox.dds"); CreateTextureFromFile(f2, &pTexture); CFileIO* f3 = CHttpIO::Open(L“http://softnette.com/checkbox.dds"); CreateTextureFromFile(f3, &pTexture);#Object Oriented Programming
  5. 5. 개발 관점의 변화 추적절차적에서 객체지향적으로재 사용성 확장성을 위한 적절한 설계가 요구됨구성 및 설계에 따른 시행 착오와 정비로 인한 개발 지연복잡도가 높아질수록 개발 효율이 떨어짐
  6. 6. 개발 관점의 변화 추적자료주도적으로프로그래머 의존도 축소개발 관점에서 생산성 향상확장성
  7. 7. 개발 관점의 변화 추적자료주도적으로스크립트손쉽게 프로그램과 연동 가능높은 유연성
  8. 8. 개발 관점의 변화 추적자료주도적으로스크립트스크립트 자체의 접근성비 프로그래머가 작성한 스크립트의 품질과 오류디버깅 이슈활용도가 높을 수록 성능 이슈
  9. 9. 개발 관점의 변화 추적자료주도적으로그래프 편집비 프로그래머들도 쉽게 접근훌륭하게 시각화된 작업 환경손쉬운 바인딩 Quartz composer확장성NDC2008: 차세대 게임 개발을 위한 실시간 비주얼 그래프 편집 vvvv http://dev.ntreev.com/publications
  10. 10. 개발 관점의 변화 추적자료주도적으로그래프 편집개발 도구의 높은 편의성이 요구됨기반 시스템 구축의 난이도 접근성복잡도와 무관하게 양이 증가할수록 직관성 감소 vvvv video visualizer
  11. 11. 개발 관점의 변화 추적컴포넌트기반 시스템객체를 컴포넌트 조합으로 구성누구나 기능 조합 가능다양한 구성이 가능 NDC2010:M2아키텍처리뷰GDC Canada 2009:Theory and Practice of Game Object ComponentArchitecture
  12. 12. 개발 관점의 변화 추적컴포넌트기반 시스템비의존적, 독립적인 컴포넌트 제작의 난이도개발 효율 저하 덜(?) 직관적인 코드 간접 참조의 스트레스내부 통신으로 인한 성능 문제 GDC Canada 2009:Theory and practi…
  13. 13. 개발 요구사항일반화도 잘 되면서 구조가 단순하고, 자료주도적이며, 다양한 기능 조합도 가능하고,개발 스트레스 없이 빠르게 개발 가능한 방법이 목표입니다
  14. 14. 슈퍼클래스한마디로, 하나의 클래스에서 모두 구현모두(?) 익숙하지만 지양하고 싶은 모델
  15. 15. 슈퍼클래스기반 게임오브젝트한마디로, 하나의 클래스에서 모두 구현모두(?) 익숙하지만 지양하고 싶은 모델역 발상으로 다기능을 지향
  16. 16. 슈퍼클래스기반 게임오브젝트한마디로, 하나의 클래스에서 모두 구현모두(?) 익숙하지만 지양하고 싶은 모델역 발상으로 극단적인 다기능을 지향
  17. 17. 셰이더로 보는 사례슈퍼 셰이더 사례 (aka. UberShader)실시간 렌더링의 패러다임 변화 고정 파이프라인에서 프로그래머블 셰이더 시대로셰이더 시스템 렌더링에 최적화된 프로세스 유닛 단순한 구성, 대량의 프로세스 유닛 추구 동적 분기 취약 하나의 머트리얼은 하나의 셰이더 (혹은 technique)
  18. 18. 셰이더로 보는 사례조합이슈float4 ps(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy);}float4 ps_light(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy) * Lambert(In.Normal.xyz);}float4 ps_lightmap(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy) * tex2D(LightMapSampler, In.Texcoord1.xy);}technique textureonly { pass p0 { VertexShader = compile vs_3_0 vs(); PixelShader = compile ps_3_0 ps(); }}technique light { pass p0 { VertexShader = compile vs_3_0 vs(); PixelShader = compile ps_3_0 ps_light(); }}technique lightmap { pass p0 { VertexShader = compile vs_3_0 vs(); PixelShader = compile ps_3_0 ps_lightmap(); }}
  19. 19. 셰이더로 보는 사례조합이슈그림자 기능 추가시 (두 배 증가)float4 ps(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy);}float4 ps_light(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy) * Lambert(In.Normal.xyz);}float4 ps_lightmap(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy) * tex2D(LightMapSampler, In.Texcoord1.xy);}float4 ps_withshadow(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy) * ProjShadow(In.ShadowPos);}float4 ps_light_withshadow(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy) * Lambert(In.Normal.xyz) * ProjShadow(In.ShadowPos);}float4 ps_lightmap_withshadow(PS_IN In) : COLOR{ return tex2D(DiffuseMapSampler, In.Texcoord0.xy) * tex2D(LightMapSampler, In.Texcoord1.xy) * ProjShadow(In.ShadowPos);}
  20. 20. 셰이더로 보는 사례조합이슈그림자 기능 추가스키닝 추가 (4배)스펙큘러 마스크 (8배)리플렉션 매핑 (16배)UV스크롤 (32배)노멀맵 (64배)대단한 의지가 아니면 관리가 불가능일정 시점 이상이 되면 셰이더의 난이도와 상관없이 작업 불가능한 상태대부분 정책적으로 기능을 제한하는 방향으로
  21. 21. 셰이더로 보는 사례조합해법코드 생성그래프 편집셰이더 조합 스크립트UberShader Unreal3 Material Editor
  22. 22. 셰이더로 보는 사례UberShader소스 코드는 유지하고 전처리를 통해서 기능 선택 float4 ps(PS_IN In) : COLOR { float4 out = tex2D(DiffuseMapSampler, In.Texcoord0.xy); #ifdef _LIGHT out *= Lambert(In.Normal.xyz); #endif #ifdef _LIGHTMAP out *= tex2D(LightMapSampler, In.Texcoord1.xy); #endif #ifdef _SHADOW out *= ProjShadow(In.ShadowPos); #endif return out; } technique complete { pass p0 { VertexShader = compile vs_3_0 vs(); PixelShader = compile ps_3_0 ps(); } }
  23. 23. 슈퍼클래스 특징1. 요구사항을 구현함에 있어서 구조적인 부담이 굉장히 적다2. 쉽게 자료화 할 수 있다3. 도구화할 수 있다4. 표준화하여 다양한 파트에 적용할 수 있다
  24. 24. 슈퍼클래스 적용 시나리오이동하는 코드를 이용해 가상의 사례를 하나구성해봅니다void CActor::Move(const Vec &dv, int lv){ float t = SweepTest(m_Pos, m_Radius, dv, NULL); m_Pos += dv * t;}
  25. 25. 슈퍼클래스 적용 시나리오요구 사항 : 어떤 객체는 충돌이 없습니다void CActor::Move(const Vec &dv){ if (m_flags&_NOCOLLISION) { m_Pos += dv; return ; } float t = SweepTest(m_Pos, m_Radius, dv, NULL); m_Pos += dv * t;}
  26. 26. 슈퍼클래스 적용 시나리오요구 사항 : 슬라이딩이 되어야 합니다void CActor::Move(const Vec &dv, int lv){ if (m_flags&_NOCOLLISION) { m_Pos += dv; return ; } Plane p; float t = CMomo::GetInstance().SweepTest(m_Pos, m_Radius, dv, &p); if (t < 1.0f) { if (t > 0) m_Pos += dv * t; if (lv < 3) { Vec vr = dv * (1-t); float d1 = p.Distance(m_Pos) - m_Radius; Move(vr - p.Normal() * Vec::dot(vr, p.Normal()), lv+1); } return; } m_Pos += dv;}
  27. 27. 슈퍼클래스 적용 시나리오요구 사항 : 슬라이딩 안 하는 객체도 있어요void CActor::Move(const Vec &dv, int lv){ if (m_flags&_NOCOLLISION) { m_Pos += dv; return ; } Plane p; float t = CMomo::GetInstance().SweepTest(m_Pos, m_Radius, dv, &p); if (t < 1.0f) { if (t > 0) m_Pos += dv * t; if ((m_flags&_SLIDING) && lv < 3) { Vec vr = dv * (1-t); float d1 = p.Distance(m_Pos) - m_Radius; Move(vr - p.Normal() * Vec::dot(vr, p.Normal()), lv+1); } return; } m_Pos += dv;}
  28. 28. 슈퍼클래스 적용 시나리오요구 사항 : 바닥에만 슬라이딩하게 해주세요.바운딩도 필요합니다. 슬라이딩시 마찰력을적용해주세요. 단, 무적상태가 아닐 때 만.충돌할 때 이벤트를 발생시켜 주세요. 대미지중 이동할 때는 충돌 지점에 파티클 좀 뿌려주세요. 단,캐릭터가 HP10%이하인 경우만….
  29. 29. 슈퍼클래스 적용 시나리오요구 사항 : 바닥에만 슬라이딩하게 해주세요.바운딩도 필요합니다. 슬라이딩시 마찰력을적용해주세요. 단, 무적상태가 아닐 때 만.충돌할 때 이벤트를 발생시켜 주세요. 대미지중 이동할 때는 충돌 지점에 파티클 좀 뿌려주세요. 단,캐릭터가 HP10%이하인 경우만….NO PROBLEM
  30. 30. 슈퍼 클래스기반 프로그래밍의 장단점장점1. 구조적으로 큰 부담 없이 기존코드를 유지하면서 새로운 기능 추가 가능기능 코드만 추가하고 객체를 생성할 때 선택적으로 해당기능을 set 시켜주기만 하면 끝2. 쉽고 단순하고 직관적단점1. 코드가 조잡해지는 느낌2. 하드코딩 하는 느낌
  31. 31. 인식의 전환코드가 조잡해 보인다어떤 식으로 구성하더라도 결과적으로 핵심 구현로직이 다른 코드일까현재 코드의 쾌적함을 위해 기획자와 명세를 협상하고 있는 건 아닌지 성찰해봅니다 “우리는 바닥에서만 슬라이딩은 불가능합니다. 끝”약간 심적인 부담이 있겠지만 쿨~하게 구현해 주는 것이 완벽한 프로그래머보다 멋진 프로그래머솔루션 : 심리적인 해결. “조잡해 보이는 건 명세 탓!! 하지만 로직을단순하고 멋지게 유지하는 것보다는 명세가 우선이다”라고 암시 암시 암시
  32. 32. 인식의 전환하드 코딩 같아 보인다일관성을 유지하면서도 관리가 가능하게 작성된코드라면 하드코딩과 다르다 (암시) if (m_Type == _WOLF && m_HP <= 10) PlaySound(L"아파"); if ((m_Flags&_HURT_SOUND) && m_HP <= m_HurtsAlramHP) PlaySound(L"아파"); void CGameRoom::LeaveRoom(CSession* session, bool graceful) { if (!IsLobby()) NotifyLeaveMessage(session); if (IsDungeon() && graceful == false) session->ExitPenalty(); } void CGameRoom::LeaveRoom(CSession* session, bool graceful) { if (m_flags&_NOTIFY_LEAVE) NotifyLeaveMessage(session); if ((m_flags&_EXIT_PENALTY) && graceful == false) session->ExitPenalty(); }
  33. 33. 슈퍼클래스화하나의 클래스에 기능을 통합인스턴스 생성시 기능 선택
  34. 34. 자료화자료 주도적으로 개발하려면 필수슈퍼 클래스 구성 요소기능 리스트기능에 필요한 속성컴포넌트기반 오브젝트 시스템과 유사
  35. 35. 자료화단순한 계층의 XML(혹은 jason)로 쉽게 표현가능<actor> <player mask="_UPDATE,_RENDER,_GRAVITY,_USERCONTROL,_CHECKEVENTBOX,_MOUSEACTION"> <pos>0 15</pos> <radius>0.5</radius> </player> <helper mask="_UPDATE,_RENDER,_STATIC"> <pos>0 2</pos> <radius>0.4</radius> <color>ffffff00</color> <name>helper</name> </helper> <camera mask="_UPDATE,_CAMERA,_NOCOLLISION"> <pos>0 10</pos> <follow>player</follow> </camera></actor>
  36. 36. 도구화기능 리스트 (on/off/enum)기능이 set 되었을 때 필요한 속성/에디터객체 1 2
  37. 37. 도구화기능명시 <particlemask type="propertysheet" minheight="75" height="25%" headervisible="false"> <shape text="형태"> <_SHAPE text="타입" type="enum" items="빌보드;트레일;메시">랜덤</_SHAPE> <_COLOR text="색상" type="enum" items="상수;보간;화이트">화이트</_COLOR> <_ALPHA text="알파" type="enum" items="없음;상수;보간">없음</_ALPHA> <_SIZE text="크기" type="enum" items="기본;랜덤;랜덤보간">기본</_SIZE> <_ROTATE text="회전" type="enum" items="없음;상수;랜덤">없음</_ROTATE> </shape> <lifetime text="생성"> <_DELAY text="생성지연" type="enum" items="없음;상수;랜덤;순차적">없음</_DELAY> <_LIFETIME text="라이프타임" type="enum" items="상수;랜덤">랜덤</_LIFETIME> </lifetime> <position text="위치"> <_POSITION text="생성위치" type="enum" items="원점;랜덤구">원점</_POSITION> <_VELOCITY text="속도" type="enum" items="없음">없음</_VELOCITY> <_DIRECTION text="방향/목표" type="enum" items="없음;랜덤구;목표지점">없음</_DIRECTION> <_GRAVITY text="중력" type="bool">false</_GRAVITY> </position> <parameters type="propertysheet" height="100%"> <general text="일반" mask="default"> <COUNT text="생성갯수" type="int" min="1" singleStep="5">10</COUNT> <LOOP text="반복" type="bool">false</LOOP> <BLEND text="블랜딩" type="enum" items="알파블랜딩;가산;곱하기">가산</BLEND> </general> <billboard text="빌보드" mask="_SHAPE=빌보드"> <TEXTURE text="texture" type="texture">check.bmp</TEXTURE> </billboard> <randomlifetime text="라이프타임" mask="_LIFETIME=랜덤"> <LIFETIME_MIN text="min" type="float" min="0" singleStep="1">5</LIFETIME_MIN> <LIFETIME_MAX text="max" type="float" min="0" singleStep="1">10</LIFETIME_MAX> </randomlifetime> <constlifetime text="라이프타임" mask="_LIFETIME=상수"> <CONSTLIFETIME text="lifetime" type="float" min="0" singleStep="1">5</CONSTLIFETIME> </constlifetime> <constcolor text="색상" mask="_COLOR=상수"> <CONSTCOLOR text="색상" type="color">ffffff</CONSTCOLOR> </constcolor>
  38. 38. 도구화기능간의 관계기능 간의 관계를 데이터 상에서 검증 <shading text="셰이딩"> <_NO_LIGHTING text="셰이딩안함" type="bool">false</_NO_LIGHTING> <_USE_SPECULAR text="스펙큘러채널" type="bool" enabletest="!_NO_LIGHTING">false</_USE_SPECULAR> <_RIMLIGHTING text="림라이트" type="bool" enabletest="!_NO_LIGHTING">false</_RIMLIGHTING> </shading>
  39. 39. 도구화클래스화많은 기능 중에서 클래스에 필요한 기능한 툴 상에서 표시클래스는 데이터로만 존재
  40. 40. 슈퍼클래스기반 게임오브젝트 극단적인 사용 안을 제안합니다 게임 객체를 하나의 오브젝트 타입으로 구성 모든 게임 객체는 Actor 데이터에 의해서만 기능 set / reset 단순한 구조 신입도 알 수 있어요Note) 현재 이 구조로 프로젝트 진행하고 있습니다 (소프트네트)
  41. 41. 슈퍼클래스기반 게임오브젝트Actor(SuperActor)모든 기능을 구현 모든 객체는 길 찾기, Head tag, 동기화 등을 맘대로 활용 가능 기능 추가하고 데이터 연동만 해주면 OK (신입도 할 수 있어요)재사용성 Better (vs ObjectOrientDesign) “아이템 사라질 때 mob 사라질 때처럼 해주시면 안되나요 ?” “Re:그렇게 하세요”직접 참조 OK (vs Component-based, OOD) 메시 모델의 손의 위치를 사운드 출력 부에서 직접 참조 카메라 객체에서 플레이어의 머리본의 TM을 직접 참조 빠르고 직관적
  42. 42. 슈퍼클래스기반 게임오브젝트SuperActor“구현부가 너무 비대해지지 않을까요 ?” 구현부를 적절히 컴포넌트화한다면 납득할 수준으로 관 리가 가능 각 컴포넌트는 계층적이지 않기 때문에 단순하게 구성가 능 (일반화의 제약도 없음) 다만 과도하게 컴포넌트화하고 정리를 하는 것보다는 관리 가능한 수준에서 느슨하게 처리하는 것을 추천
  43. 43. 슈퍼클래스기반 게임오브젝트SuperActor“일일이 비트 검사하면 속도상 불이익이 있지 않을까요 ?”구현은 트리 구조를 이루게 됨 그룹단위로 체크해서 최 상위에서 skip 하도록 점프는 이동 하위에, 2단 점프는 점프 하위좀 더 도전적으로 DOD로 확장가능(슈퍼클래스기반 파티클 참조) #Data Oriented Design http://www.lameproof.com/zboard/zboard.php?id=bbs2&no=790
  44. 44. 슈퍼클래스기반 게임오브젝트SuperActor“그럼 모든 속성도 가지고 있다는 건데, 메모리 낭비가 심하지 않을지요” (필요한 경우 heap으로) template <class _Tx> class CValuePtr { public : CValuePtr() { m_Ptr = NULL; } ~CValuePtr() { if (m_Ptr != NULL) delete m_Ptr; } _Tx* operator-> () { if (m_Ptr == NULL) m_Ptr = new _Tx; return m_Ptr; } private : _Tx* m_Ptr; } ;class CActor {private: struct _DIALOG { _DIALOG() { Shape = NULL; } ~_DIALOG() { if (Shape) delete Shape; } float OpenStep; Sphere* Shape; value = *node.FindChild(L"dialog_offset"); float Offset[2]; swscanf_s(value, L"%f %f", &m_Dialog->Offset[0], &m_Dialog->Offset[1]) }; value = *node.FindChild(L"dialog_size"); CValuePtr<_DIALOG> m_Dialog; m_Dialog->Shape = new Sphere(Vec(0, 0), unicode::atof(value), 14);} ;
  45. 45. 슈퍼클래스기반 게임오브젝트슈퍼 클래스 기반 게임 오브젝트 장점단순한 구조로 빠른 개발이 가능기능 추가가 용이하며 많은 코드 공유 가능 소규모 여러 프로젝트에서 공유 가능 사이드뷰 액션 게임과 TPS, 스포츠 게임이 같은 프로젝트코드 관리 용이성 데이터 검증으로 dead code 판단 가능 Legacy code를 유지하면서 방어적으로 기능 교체
  46. 46. 슈퍼클래스기반 게임오브젝트슈퍼 클래스 기반 게임 오브젝트 장점툴 연동 가능 툴에서 필요한 기능만 활성하면 툴 상에서 인터렉션 가능 툴 내 게임 플레이도 가능 생산성 향상
  47. 47. (데모)
  48. 48. 슈퍼클래스 기반 파티클하나의 파티클 객체에서 모든 기능을 구현표준화된 도구사용절차1. 데이터를 읽어서 사용되는 기능과 툴에서 세팅한 값들을저장2. 파티클 인스턴스 생성시 인스턴스에 초기값 세팅3. 파티클 업데이트
  49. 49. 슈퍼클래스 기반 파티클생성 지연시간 예 void CParticle::InitParticle(void *data, int count) const { for(int i=0; i<count; i++) { _PARTICLE* ptr = (_PARTICLE*)((char*)data + m_Pitch * i); char * extra = (char*)ptr + sizeof(_PARTICLE); if (m_InitMask&_DELAY_CONST) { ptr->curTime = - *(const float*)GetParam(_I_DELAY_CONST); } else if (m_InitMask&_DELAY_RANDOM) { const float* delayrandom = (const float*)GetParam(_I_DELAY_RANDOM); ptr->curTime = - Random(delayrandom[0], delayrandom[1]); } else if (m_InitMask&_DELAY_SEQ) { ptr->curTime = - *(const float*)GetParam(_I_DELAY_SEQ) * i; } else { ptr->curTime = 0; }
  50. 50. 슈퍼클래스 기반 파티클업데이트 예비트 연산으로 기능 체크해서 구현 bool CParticle::Update(float dt, void * data, int count, unsigned long updatemask) const { for(int i=0, off=0; i<count; i++, off+=m_Pitch) { _PARTICLE* p = (_PARTICLE*)((char*)data + off); p->curTime += dt; char * extra = (char*)p + sizeof(_PARTICLE); if (updatemask&_COLOR_BLEND) { unsigned long* blendcolor = (unsigned long*) GetData(extra, _U_BLENDCOLOR); p->color = LerpColor(blendcolor[0], blendcolor[1], p->curTime / p->lifeTime); } if (updatemask&_GRAVITY) { Vec3* vel = (Vec3*) GetData(extra, _U_VELOCITY); *vel += Vec3(0, -9.8f, 0) * dt; // 중력 } if (updatemask&_VELOCITY) { const Vec3* vel = (const Vec3*) GetData(extra, _U_VELOCITY); p->pos += (*vel) * dt; }
  51. 51. 슈퍼클래스 기반 파티클메모리 문제오프셋 테이블을 이용하여 최소의 용량만 사용기능상 필요한 데이터만 할당
  52. 52. 슈퍼클래스 기반 파티클성능 문제분기문(if)로 인한 제어 해저드대량의 연산이 이루어지기 때문에 성능을 고려할때는 민감한 사안#control hazard
  53. 53. 슈퍼클래스 기반 파티클성능 문제해법#1 자료지향설계(DOD)bool CParticle::Update(float dt, void * data, int count, unsigned long updatemask) const{ _PARTICLE* p = (_PARTICLE*)((char*)data + off); int i; for(i=0; i<count; i++) p->curTime[i] += dt; if (updatemask&_COLOR_BLEND) { unsigned long* blendcolor = (unsigned long*) GetData(p, _U_BLENDCOLOR); for(i=0; i<count; i++) p->color[i] += LerpColor(blendcolor[i*2+0], blendcolor[i*2+1], p->curTime / p->lifeTime); } if (updatemask&_GRAVITY) { Vec3* vel = (Vec3*) GetData(p, _U_VELOCITY); for(i=0; i<count; i++) vel[i] += += Vec3(0, -5.0f, 0) * dt; } if (updatemask&_VELOCITY) { const Vec3* vel = (const Vec3*) GetData(p, _U_VELOCITY); for(i=0; i<count; i++) p->pos[i] += vel[i] * dt; }
  54. 54. 슈퍼클래스 기반 파티클성능 문제해법#2 컴파일러 마법도달하지 않는 코드, 상수연산은 제거됨#include <windows.h>inline void update(unsigned long mask){ if (mask&1) ::Sleep(0xFF); if (mask&2) ::Sleep(0xF);}void main(){ unsigned long mask = rand(); update(mask); update(2);}
  55. 55. 슈퍼클래스 기반 파티클성능 문제해법#2 컴파일러 마법많이 호출되는 타입은 아래처럼bool CParticle::Update(float dt, void * data, int count) const{ if (m_UpdateMask == (_COLOR_BLEND|_GRAVITY|_VELOCITY)) return Update(dt, data, count, _COLOR_BLEND|_GRAVITY|_VELOCITY); else if (m_UpdateMask == _COLOR_BLEND) return Update(dt, data, count, _COLOR_BLEND); return Update(dt, data, count, m_UpdateMask);}해당 기능만 실행하는 코드 생성BEST
  56. 56. 슈퍼클래스 기반 파티클슈퍼클래스 기반 파티클의 장점다양한 조합의 파티클손쉬운 도구 연동이펙트 디자이너의 요구를 빠르게 반영 가능 바로 구현 후 데이터 연동만 해 놓으면 OK “호혹시 파티클이 회오리 모양의 경로로 움질일 수 있을 까요?” “네 만들어 드리겠습니다”빠른 연산 시스템이 단순하여 병렬화나 메모리 친화적인 다양한 최 적화가 가능
  57. 57. 슈퍼클래스 기반유저 인터페이스 시스템컴포넌트의 예외적인 명세포스트 프로세싱 / 모션 컨트롤자료 주도적인 구성 셰이더 , 셰이더 변수, 블룸, 렌더 타겟,… 조합으로 패스 정의여러 패스
  58. 58. 슈퍼클래스 기반 서버일반적인 서버 구성게임의 성격에 맞도록 서버를구성기본 모듈을 공유하는 서로다른 프로젝트로 예상 게임테크 2010:Extracting MMORPG Server Engine from TERA
  59. 59. 슈퍼클래스 기반 서버슈퍼 클래스 기반의 서버 구성서버는 한 종류데이터에 의해서 기능 명세
  60. 60. 슈퍼클래스 기반 서버슈퍼 클래스 기반의 서버 구성서버는 한 종류데이터에 의해서 기능 명세다기능 서버 게임 성격과 서비스 상황에 맞도록 세팅 인증+필드, 인증+던전, 던전 인증+던정,필드 … 기능 단위보다는 지역, 처리 유저 수 기준
  61. 61. 슈퍼클래스 기반 서버클라이언트와 코드 공유클라이언트의 게임 객체를 서버에서도 사용 필요한 기능만 활성 가능하도록 제한 “길 찾기 따로 만들어야 되나요 ?” “클라이언트에서 구현한 AI캐릭터를 서버에서 사용할 수 없나요 ?” “서버용 데이터 안 만들고 애니메이션 이벤트 검증할 수 있나요?” NO PROBLEM정책적으로 클라이언트, 툴, 서버에서 게임 객체 공유 (소프트네트)
  62. 62. (데모)
  63. 63. 결론슈퍼 클래스를 이용하면구조적인 복잡도가 낮아 직관적으로 구성 가능단순한 구조로 설계 및 관리의 스트레스에서 해방구현에 좀 더 집중 가능하며 개발 속도 개선도구를 이용하여 프로젝트 개발 속도 개선코멘트 : 우아하고 섹시하진 않지만 합리적으로 검토해 볼만한 아이디어슈퍼클래스, 상태 머신, 스크립트 3S 삼총사면 무서울 게 없습니다
  64. 64. 감사합니다강연자 이메일 noerror@softnette.com

×