NDC11_김성익_슈퍼클래스

1,795 views

Published on

Super-class Based Game Object System

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,795
On SlideShare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
0
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

NDC11_김성익_슈퍼클래스

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

×