1. Creating Game Tool
With Project Anarchy
- Vision Engine을 이용한 Game Tool 만들기 Part 2-
분 류 NHN NEXT 1기 실전프로젝트 산출물
실습 업체 블루홀 스튜디오
프로젝트 팀명 그랜드부다페스트(문진상/신동찬)
작성자 문진상
Created Date 2015-1-03
2. 지난 줄거리
• 이렇게 생긴 툴을 만들어 볼 것입니다
Wrapper
Vision Engine
Client
Tool
게임 툴
클라이언트
Wrapper
3. 지난 줄거리
• Run() 함수 안에서 일어나는 일들은 엔진이 알아서 한다!
• 하지만 아무것도 안 해도 된다는 뜻은 아니다!
• 아무것도 안 하면 그냥 까만 화면만 나올 뿐…
• 그렇다면 화면을 채울 Entity를 만들어보자
4. Entity
Vision:: 네임스페이스를 이용해 별도의 선언 없이 Entity를 만드는 것이 가능
만드는 김에 조명도 하나 달아주면?
잘 나온다
Wrapper
참고로 이 함수들은 만들어진 Entity의 포인터를
리턴하기 때문에 Scale, Position 등을 바꿀 때
사용할 수 있다.
5. Tool에서 Entity가 왜 중요한가?
• Tool 에서 오브젝트를 배치하는 기능은 결국 Entity를 생성하는
기능이다
• 대부분의 게임 프로젝트에서 특성에 맞는 GameObject를 생성
하게 되는데 이때 VisBaseEntity_cl을 상속받아서 구현하는 것이
좋다
• 엔진이 지원하는 기능을 충분히 사용하려면 엔진에서 제공하는 클래스
를 쓰는 것이 좋다.
6. 몬스터와 자원을 배치해보자
• 이제 Entity를 만들 수 있으니 맵에 Entity를 놓을 수 있습니다
• 단, 일을 수월하게 하려면 picking 기능이 필요합니다.
• picking 은 마우스로 화면을 클릭했을 때 어떤 객체를 클릭했고 좌표는
어디인지를 알아내는 기능입니다.
Wrapper
EntityPicking() 함수가 Picking 시도
Picking으로 뭔가를 선택하는 데 성공
해당 좌표에 엔티티 생성
7. 몬스터와 자원을 배치해보자
1. Mouse Mode 메뉴에서 CreateEntity
2. Create Entity 페이지에서 Type을 지정
3. 화면을 클릭하면 생성 시도
순서로 진행하도록 만들었습니다.
8. 몬스터와 자원을 배치해보자
Tool
위 코드는 “좌클릭 이벤트가 발생하고”, “CreateEntity 라디오 버튼이 체크되어 있으면”
RayTraceAndCreateEntity 함수를 호출해서 선택된 타입의 Object를 생성하도록 되어 있다
11. 여기서 잠깐
Tool
Wrapper(EntityEditor)
Wrapper(GameObjectForTool)
코드의 재사용성을 높이려면, 보통 엔티티 생성 같이 Client와 Tool
모두 사용하는 코드는 Client에 두는 것이 좋습니다.
Tool
Wrapper(EntityEditor)
Client(GameObjectManager)이런 식으로…
왜냐하면 어차피 클라이언트는 C++로 되어 있고, Wrapper가
클라이언트에서 C++로 구현한 기능을 이름 그대로 감싸기만 하면
C#에서도 그대로 쓸 수 있기 때문입니다.
사실 그러려고 Wrapper를 만든 것인데…
13. 여기서 잠깐
• 문제는 Calling Convention
• Client는 ProjectAnarchy에서 기본 제공하는 빈 프로젝트에서
만들기 시작
• 각종 세팅이 기본으로 잡혀있는 반면
• /clr 옵션을 준 Wrapper에서 Client 코드를 불러다 쓰면 에러 발생
• MSDN에 의하면 이 문제를 해결할 수 있긴 한데… 해결책도 만만하지
않습니다
14. 여기서 잠깐
그래서 복사했습니다… 제 의지로….
Client(GameObjectManager)
Tool
Wrapper(EntityEditor)
Wrapper(GameObjectForTool)
Copy & Paste
이러면 Calling Convention 문제가 발생하지 않지만
1. 하지만 코드가 중복되고
2. Wrapper 안에 또 Wrapper가 있어서 수정이 어려워짐
15. 지형은 어떻게 만드나
• ProjectAnarchy 에서 지형과 관련된 클래스는 상당히 많음
• 하지만 대부분 게임 엔진들이 그렇듯이 자체적으로 제공하는
vForge툴로 지형을 생성하는 것을 권장한다
• 당연하지 이게 훨씬 편하니까요
• 코드로 지형을 직접 만드는 예제가 부족하다
• 삽질 끝에 static mesh 를 사용하기로 결정
• 사실 코드로 만들어서 되는 방법을… 아직 이거밖에…
17. 지형은 어떻게 만드나
• 큰 흐름은 이렇습니다
• 사용자 정의 Vertex 구조체를 만든다
• 사용자 정의 Vertex 구조체가 어떻게 생겼는지 전달해주는 버텍스 기
술자를 만든다.
• MeshBuffer 를 만든다
• MeshBuffer를 이용해서 StaticMesh를 만든다
• StaticMesh를 이용해서 StaticMeshInstance를 만든다
18. 왜 이렇게 단계가 많지?
• 엔진을 썼으면 엔진 법을 따라야(…)
• 화면에 렌더링 되는 부분을 엔진이 관리해주고
• 마우스 포인터로 Picking 했을 때 확인이 되고
• 메모리 관리까지 해줌
• 사실 MeshBuffer만 있어도 렌더링은 할 수 있다!
• DirectX 예제를 떠올리면 됩니다
• 하지만 내부에 숨어있는 RenderingLoop에 손을 대야 하고
• 제일 큰 문제는 마우스로 picking 했을 때 없는 물체 취급
19. 지형 관련 중요 클래스 생성 흐름
이 단순한 구조체가 지형에 사용할 Vertex입니다
hkvVec3 는 3차원 벡터, hkvVec2는 2차원 벡터입니다
Vertex의 위치와 노말 벡터의 방향, 텍스처의 uv 값을
표현하기 위한 최소한의 멤버만 들고 있습니다
Vertex의 형식은 고정된 것이 아니므로 게임 엔진에게
내가 만든 Vertex 형식을 알려주는 과정이 필요합니다
Vertex 기술자에게 Vertex의 사이즈,
Position 변수가 무엇인지 등등을
알려줘야 합니다
Wrapper
20. 지형 관련 중요 클래스 생성 흐름
MeshBuffer를 만들어 줍니다.
옵션은 INDEXED_TRILIST
MeshBuffer에 락을 잡고
Vertex에 값을 넣어줍니다.
옆의 코드는 평평한 정사각형
Wrapper
21. 지형 관련 중요 클래스 생성 흐름
Static Mesh를 만들고
조금 전에 만든 MeshBuffer를
옵션으로 넣어줍니다
Texture 달기
없어도 동작은 하지만 지형이
하얀 사각형으로 보입니다
Wrapper
22. 지형 관련 중요 클래스 생성 흐름
StaticMesh 에서
Submesh 설정
대망의 StaticMeshInstance. 사실 이 클래스를 만들기 위해 지금까지의 과정이 필요한 것입니다
AssignToVisibilityZones()를 통해 렌더링을 맡길 수 있고 Picking까지 지원됩니다
Wrapper
23. 지형 올리고 내리기
• Picking이 되므로 해당 좌표의 vertex 주변을 같이 올리고 내려
주면 된다
잘 된다. 잘 되는데…
24. 지형 올리고 내리기
• 버그가 있다
• Picking을 할 때 StaticMesh가 가리키고 있는 MeshBuffer가 아
니라 CollisionMesh를 기준으로 계산
• CollisionMesh는 눈에 보이지 않음
• 눈에 보이게 그릴수도 있는데 Debug용 함수라 매 프레임 호출하도록
RenderingLoop를 손대야 함
• 지형을 올리고 내리기 위해 MeshBuffer의 Vertex만 조작하도록
했는데 CollisionMesh는 변화가 없다!
• 아무리 산과 계곡을 만들어도 Picking은 평면만 찍힘
25. 지형 올리고 내리기
• Entity를 만들 때 Picking을 기반으로 하므로 Entity가 산에 파묻
히거나 계곡 위에 떠 있음
• Entity를 만들기 전에 MeshBuffer에 변화가 있으면
CollisionMesh를 재계산 하는 코드를 넣어서 해결(느리다)
Collision Mesh
Picking
Hit!
?
이상한 곳에 맞는다 Mesh Buffer
26. File I/O
• 지형의 MeshBuffer 및 몬스터, 자원 등 모든 객체의 정보는 메
모리에 올라가 있다
• 이걸 파일에 쭉 쓴 다음 다시 읽어 들여 초기화하는 데 사용하
면 데이터를 저장할 수도 있고 Tool에서 만든 파일을 Client에서
사용할 수도 있음
• 물론 I/O 규약을 정해서 지켜야 함
• 지형처럼 매우 큰 데이터도 주고받을 수 있다
27. 부록 C++/CLI Beginning
Native C++
관리 클래스
위의 클래스는 C#에서는 보이지 않는다.
아래 클래스는 관리 클래스로 C#에서도 불러서 쓸 수 있다.
관리 클래스로 비관리 클래스를 감싸서 C#과 C++사이의 다리가 되는 것이 Wrapper의 역할
28. 부록 C++/CLI Beginning
ref 클래스의 ^는 비관리 클래스의 *에 해당한다.
용법이 포인터와 비슷하다. (엄밀히 말하면 ^는 핸들이다)
만약 new를 쓸 일이 있으면
CommonVector3^ vec3 = gcnew CommonVector3;
하면 마치 C#에서 new 쓰듯 메모리를 관리해준다
C++ 참조자(&)에 해당하는 것은 %이다.