가끔씩 작업을 하다가 작업 중인 액터의 블루프린트 에디터를 열려고 하면 충돌 에러가 발생할 때가 있다.

 

 

만약 충돌 에러가 발생할 시 해당 액터의 디테일에 블루프린트 편집을 누르고

"인스턴스 변경사항을 블루 프린트에 적용"을 클릭을 해주면 해결된다.

 

위에 있는 충돌 에러 사진은 해당 오류와 관련이 없는 사진이다....(오류가 발생했을 때 캡처못함...)

 

소프트렌더러 프로젝트에 여러 개의 게임 오브젝트를 구현.

GameEngine.cpp / LoadScene

 

 

소프트렌더러 프로젝트에서 카메라를 따라 플레이어를 구현

SoftRenderer2D.cpp / Update2D

 

 

결과

 

 

소프트렌더 전체 프로세스 정리

 

 

 

렌더링 파이프라인 

 

GameEngine, GameObject2D 클래스에서 각 멤버 변수 유형에 대한 적절한 이유는?

 

Smart Pointer에는 세 가지 포인터가 존재한다.

1. Shared_ptr : 인스턴스를 가리키는 포인터의 갯수를 카운팅하여 메모리 누수가 발생하지 않도록 한다.
2. unique_ptr : 하나의 포인터만이 해당 인스턴스를 가리킬 수 있도록 한다.
3. weak_ptr : 하나 이상의 shared_ptr가 가리키는 객체를 참조할 수 있지만 reference count를 늘리지 않는다.

 

C#과 언리얼에서는 unique_ptr이 아닌 Shared_ptr을 사용한다.

왜냐하면 C#과 언리얼 엔진에서는 GC(가비지컬렉션)를 통해서 메모리를 관리하기 때문에 어쩔 수 없이

Shared_ptr을 사용을 해야한다.

 

_Player

_QuadMesh

_Camera2D

 

위에 3가지 멤버 변수는 각각의 인스턴스에 대한 유니크 포인터이다.

이것을 사용하는 이유는 파생 클래스를 처리하거나 또는 원하는 곳에서 객체를 생성과 소멸시키기 위해서이다.

 

_Transform 

Transform2D는 하나의 변수로 선언한다. 왜냐하면 모든 게임 오브젝트는 최소 하나씩의 값을 가지고 있기 때문이다.

 

_MeshPtr

Mesh는 일반 포인터를 사용한다. 왜냐하면 Mesh는 엔진을 초기화할 때 이미 생성된 초기 Mesh 데이터를 사용하기

때문이다. 또한 Mesh 데이터는 처음에 생성이 된 후에는 변화가 생겨서는 안 된다.

GameEngine에서 필수 코어 클래스란 GameObject, Resources 등을 말한다.

이 필수 코어 클래스를 관리하기 위해서는 해당되는 컨테이너를 선택해서 GameEngine의 구조를 구성해야 한다.

 

그 이유는 전체 게임 엔진 프로세스 중에 각각의 중요한 기능 호출에서 발생한

실제 동작(단일 항목 검색, 삽입/삭제, 트래버스)에 근거해야 한다.

 

먼저 엔진에서 모듈 구성과 순서는 다음과 같다.

여기서 엔진에서 렌더러 모듈로 데이터를 넘겨줘야 하는데 그것에 필요한 데이터는 무엇인가?

게임엔진에서 관리해야하는 데이터는 다음과 같다.

리소스 매니저에는 리소스, 리소스에는 데이터, 경로, 키, 타입이 존재한다.

(여기서 타입은 Mesh, Texture, Prefab을 의미한다.)

 

씬 매니저에는 게임 오브젝트, 게임 오브젝트에는 트랜스폼이 존재한다.

 

이 데이터들을 각각 어떤 컨테이너를 사용해서 구현을 해야 할지 생각해봐야 한다.

사용 할 컨테이너는 다음과 같다.

 

Map

Unordered_Map(Hash Map)

Vector

 

Map에서는 정렬은 빠르지만 속도는 느리다는 단점이 있고,

Unordered_Map에서는 속도는 빠르지만 정렬되지 않는다는 단점이 있다.

Vector는 메모리에 데이터가 순차적으로 저장되어있기 때문에 효율적으로 요소 조회가 가능하다.

 

  • 씬 매니저와 리소스 매니저에서는 어떤 컨테이너를 사용해야 좋을까?

게임의 실행 구도를 살펴보면 씬로딩 -> 리소스 로딩 -> 렌더링처리 순으로 실행이 된다.

 

씬 매니저에서는 Vector를 사용해야 한다고 생각한다.

 

그 이유는

렌더링 처리를 하려면 처음부터 끝까지 다 돌아야 하기 때문에 성능 부분을 고려한다면

어쩔 수 없이 Vector를 사용해야 하기 때문이다. 

 

그렇다면 리소스 매니저는 어떤 컨테이너를 사용해야 좋을까?

 

어떤 게임 오브젝트가 있을 때 리소스에 대한 것은 리소스 매니저가 가지고 있다.

 

씬 매니저에서 Vector를 사용한다면 이 게임 오브젝트는 Vector로 관리가 되고 있기 때문에

처음부터 끝까지 순차적으로 로딩을 하게 된다.

 

순차적으로 로딩이 되는 과정에서 리소스 매니저는 리소스의 키값을 가지고 가서 빼오게 되는데,

이 부분에서는 따로 정렬이 될 필요가 없다고 생각해서 씬 매니저와 같이 Vector를 사용해야 한다고 생각한다.

 

왜냐하면 특정 아이템을 보여주는 것이 아닌 처음부터 끝까지 다 보여줘야 되는 것이기 때문이다.

 

따라서 리소스 매니저는 정렬이 의미가 없기 때문에 에디터 인터페이스까지 감안하면 Vector를 사용해야 좋지만,

만약 리소스를 검색하는 용도로만 사용을 하는 것이면 Unordered_Map이 더 좋다고 생각한다.

클래스와 구조체는 거의 동일한 구조와 기능을 가지고 있지만 접근 지정자 부분에서 다르다.

 

클래스의 경우는 접근제어 지시자를 따로 지정하지 않는 경우 private으로 선언이 되고,

구조체의 경우는 public으로 선언이 된다는 차이점이 있다.

 

접근 지시자의 경우 다음과 같이 세 가지가 존재한다.

 

public : 어디서든 접근이 가능

protected : 상속관계 일 때 접근이 가능

privatet : 클래스 내부에서만 접근이 가능

 

  • 클래스가 아닌 구조체를 사용하는 이유는?

구조체는 값 타입이므로 클래스 사용 시 참조로 인한 시간과 비용적 낭비를 줄일 수 있다.

만약 클래스 내부에 값 타입만 담아서 사용을 하게 된다면 구조체를 사용하고,

그렇지 않다면 클래스를 사용하는 것이 좋다고 생각한다.

 

  • Math Library에서 구조체를 사용하여 정의하는 이유는?

Math Library의 경우에도 값 타입으로만 만들어져 있기 때문에 위에서 설명한 것처럼 시간과 비용적 낭비를 줄이기 위해

구조체를 사용한다고 생각한다.

 

엔진에서 예로 들면 유니티나 언리얼 엔진 내의 Math Library에서도 구조체를 사용하고 있다.

 

  • 유니티와 언리얼을 비교하자면 C#과 C++의 Struct의 차이점은 무엇인가?

C++에서는 클래스와 구조체는 거의 동일하다고 볼 수 있지만 C#에서는 용도 자체가 다르다.

C#의 구조체는 상속을 지원하지 않으며 명시적 기본생성자를 지원하지 않는다.

 

또 하나 다른 점으로는 기본 접근제어 지시자도 다르다.

C++에서 클래스의 기본 접근제어 지시자는 "private", 구조체는 "public" 으로 선언 되지만,

C#에서는 클래스와 구조체 둘 다 "private" 으로 선언된다.

 

C#에서 클래스는 항상 힙 영역에 생성이된다.

하지만 구조체는 항상 스택에 생성되는 것이 아니고 초기화를 해줘야 힙에 생성하게된다.

 

 

 

+ Recent posts