iterator로 for문 돌던 것을 좀 더 편하게 돌 수 있다.
값을 다 돌면서 읽거나 수정할 수 있다. 노드 삭제 등의 자료구조를 변형시키는 연산은 하지 말아야 한다.
#include <iostream>
#include <list>
#include <map>
int main() {
std::list<int> NewList;
for (int Value : NewList) {
// Value로 NewList의 값을 다 돌 수 있다.
}
// 레퍼런스로 수정하고 싶다면
for (int& Value : NewList) {
}
std::map<int, int> NewMap;
// 참조가 넘어옴
for (std::pair<const int, int>& Map : NewMap) {
}
}
주의점) Ranged for를 돌리는 동안 자료구조의 메모리 구조가 변경되면 치명적인 에러를 낼 수 있다. 예를 들면 for문 안에서 erase().
오브젝트라는 개념 <- 화면에 존재하는 개념들을 엔진이 어떻게 지원하느냐
릴리즈 <- 이런 애들이 사라졌을 때 어떻게 정리하느냐
랜더링 <- 화면에 어떻게 그리느냐
콜리전 <- 화면안에 존재들이 어떻게 상호작용하느냐
엔진코어가 두 개 이상일 일이 없음. -> 생성자를 protected로 둔다. 아무나 생성할 수 없도록.
(그래서 KirbyCore도 괜히 만들었나 라는 생각)
화면에 보이는 애들뿐만이 아니라 장면이라는 개념을 표현하려고 노력한다.
쉽게 말하면 스테이지. 그런 '장면'을 언리얼에서는 level, 유니티에서는 scene이라는 개념으로 표현한다.
level은 플레이 레벨만 있는 게 아니고 타이틀 - stage1 - 엔딩
다 포함된다.
레벨을 여러 개 만들어도 되고 한 개만 만들어서 재활용(?)해도 된다.
UObject와 AActor
A가 붙은 오브젝트는 화면에 위치가 존재해야 한다.
U가 붙은 오브젝트는 엔진에 속해있다는 것을 의미한다. (위치를 가지지 않음)
고민해야하는 것들
어떻게 레벨을 만들까
어떻게 레벨을 보관할까
어떻게 다른 객체들이 레벨을 사용할 수 있게 만들까
나는 아직 커비 컨텐츠에 대한 코드가 없기 때문에 선생님이 예시로 만드시는 Contents라는 컨텐츠로 엔진 구조를 이해해봤다.
우선 Level0~Level3의 엔진 구조와 Level4의 main이 있다. App에서 wWinMain함수로 진입하여 시작하게 된다.
이후 실행되는 흐름이다.
wWinMain에서 EngineStart함수를 실행하여 컨텐츠 코어를 만들고 창을 띄우게 된다.
또 그 코어를 이용해서 레벨을 만들고 시작한다.
메시지루프에서는 EngineTick을 반복 실행하도록하여 업데이트한다. EngineTick에서는 각 레벨들과 액터들의 Tick(업데이트)을 진행한다.
GEngine이 extern 전역 변수인 이유
GEngine이 전역 변수이고 EngineStart에서 컨텐츠코어를 업캐스팅한 Ptr을 넘겨준다. 그럼 이후로 EngineCore.h 헤더를 include했다면 항상 GEngine으로 하나뿐인 엔진코어를 사용할 수 있게 된다. static이어도 똑같은데 언리얼에서는 extern으로 하고 있기 때문에 extern으로 만든 것이다.
_DeltaTime
: 이전 프레임에서 지금 실행된 프레임까지의 사이 시간