+ 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!



기본적인 C++의 const에 대한 기록


const는 크게 2곳에서 사용된다.

1. 변수

2. 함수



1. 변수

1) const int val;

- val의 데이터 형이 (const int)형이므로 값을 수정할 수 없다.


2) const int* val;

- val은 (const int)형의 포인터 값이다.

- val의 값은 수정 가능하다.

- val이 가리키는 데이터는 (const int)형이므로 수정 불가능.


3) int* const val;

- val의 데이터 형은 int*형이고, const 키워드로인해 수정 불가능하다.

- val이 가리키는 데이터는 (int)형이므로 값을 수정할 수 있다.


4) const int* const val;

- val의 값이나 val이 가리키는 데이터나 둘 다 수정 불가능.



2. 함수

1) const int foo()

- foo()의 반환 데이터 평이 (const int)이므로 반환값은 수정 불가능하다!


2) int foo() const

- 표현하자면 int foo() const { 함수 내용 }; 이므로, 함수 내용에서 멤버 변수 값을 수정하지 않겠다는 의미다.

- 멤버 변수 값을 수정할 수 없다보니, 사용할 수 있는 함수들도 const형 함수들 만 사용할 수 있다. 이 이외는 에러가 발생.

- 이런 특성때문에, Get함수에서 많이 사용하고, Set함수에서는 거의 사용하지 않는다.





Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

 + 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!


흠... Unreal Engine의 기본 상태? 및 관리?라고 할 수 있는 것들을 알아보자!

( 어차피, 공식 Docs를 참고한거... )


*말투가 이상할 수 있는데, 그건 그냥 정리하면서 작성하다보니 그렇습니다.


<GameMode / GameState>

 

 + 기본적으로 게임에 대한 기본 규칙들을 지정하는 곳이 GameMode,

 + 게임이 돌아가고있는 상황에 대한 정보들을 저장하는 곳이 GameState.

 


[AGameModeBase]

 + 예전 언리얼 버전에서는 GameMode를 베이스로 사용했는데, 4.14버전 이후로 GameModeBase라는 것이 생겼다.

그 이유는 여러 게임에 호환성있게 사용하기 위함인데, GameMode는 기본적으로 멀티플레이어슈팅게임에 어울리도록 구성되어있다.

(아마 언리얼이 그런 장르를 기본으로 만든 엔진이라서 그럴지도)

그리서 다른 종류의 게임에서 사용할 수 있도록 GameMode의 부모인 GameModeBase를 만들었다.

내부에 다양한 함수가 있지만, 기본적으로

(작성 순서대로 실행됨)

 

// Init

InitGame

 - 해당 함수는 다른 Actor들을 포함해서 PreInitializeComponents가 실행되기전에 실행된다.

 - 말 그대로 Game 시작 전에 규칙을 설정한다는 느낌

 

// login

PreLogin

 - 서버로 접근하려는 플레이어를 처리할 때, 실행되는 함수.

PostLogin

 - 플레이어가 서버에 접근 완료하고 나서 실행되는 함수.

 

// Creage Player

HandleStartingNewPlayer

 - PostLogin이 실행되고나서 실행되며, 새로운 Player에게 적용할 일들을 처리한다.

 - 이 함수에서 새로운 Player를 생성한다.

RestartPlayer

 - 폰이 생성되기 위해서 실행되는 함수

 - 여러 함수가 있지만, 스폰 위치를 설정하기 위한 RestartPlayerAtPlayerStart / RestartPlayerAtTransform 함수 들이 있다.

 - BP에서 바인딩해서 사용할 수 있게 OnRestartPlayer함수도 있다.

SpawnDefarulPAwnTransform

 - 실제로 Player's Pawn을 생상하는 로직.

 - BP에서 Override해서 사용할 수 있다.

 

// Logout

Logout

 - Player가 게임을 떠나거나 소멸되었을 때, 실행되는 함수.

 - OnLogout을 Implement해서 사용할 수 있다.

(Override는 부모 로직이 있고 내가 재설정을 해서 사용할 수 있다면, Implement는 원하면 구현해서 사용할 수 있는 것)


와 같은 함수들이 존재한다.

 

 + 게임모드 액터는 UGameEngine::LoadMap(...)을 실행할 때, 플레이할 레벨을 초기화시킬 때 마다 인스턴스를 만든다.

 

(멀티게임 기준)

 + 서버를 두는 게임인 경우, 게임모드는 서버에서 관리하고 원격 클라로 정보를 리플리케이트 하지 않습니다. 게임 모드 정보만 읽을 수 있고, 실제 인스턴스에 접근해서 변동사항을 확인할 수 없습니다. 만약, 업데이트된 정보가 필요한 경우에는 GameStateBase를 통해 확인할 수 있습니다. 서버에서 게임모드와 함께 생성해서 클라이언트로 리플리케이트 하기 때문.

 

 

[AGameMode]

 + 예전에 기본으로 사용했던 AGameMode클래스.


 + 해당 클래스는 내부적으로 match state machine을 지원하는데, 그러다보니 해당 클래스는 사용하려면 GameState도 같은 match state machine을 지원하는 AGameState클래스를 상속해야합니다.


 + 내부적으로 match state machine을 통해 game flow를 추적할 수 있으며, 

GetMatchState, HasMatchStarted, ISMatchInProgress, HasMatchEnded등의 함수를 통해 현재 상황을 알 수 있다. 


<State>

EnteringMap

 - 맵 진입 초기단계로, 아직 맵은 로딩 중이며 Tick도 활성화되지 않은 단계

WaitingToStart

 - 게임 시작 전 대기단계로, Actor Tick은 돌아가지만 Player가 스폰되지 않은 상태.

 - ReadyToStasrt가 true를 반환하거나 StartMatch가 호출되면 다음 상태로 이동.

InProgress

 - 대부분 Player가 머무는 상태로, HandleMatchHasStarted가 호출되고 모든 Actor이 BeginPlay가 호출되는 부분.

 - ReadyToEndMatch가 true를 반환하거나 EndMatch가 호출되는 경우 다음 단계로 이동.

WatingPostMatch

 - 끝에서 2번째 단계.

 - HandleMatchHasEnded가 호출.

 - Actor Tick은 호출되지만, 새로운 Player는 참가 불가능

 - 맵 이동 시, 다음 단계로 이동

LeavingMap

 - 끝 단계

 - 이 단계로 들어갈 때, HandleLeavingMap이 호출되며, 맵 전환이 일어다면 다시 EnteringMap단계로 이동한다.

Aborted

 - 실패 단계로, AbortMatch를 호출하거나 복구할 수 없는 오류가 발생했을 때, 설정된다.

 

 + 기본적으로 제공해주는 state들이 있고 많은 시간 InProgress에 머물 것입니다.

그리고 개발자가 원한다면 Override해서 state를 추가해서 사용할 수 있다.

 

 + EpicGames-Launcher 내부에보면 DefaultEngine.ini 파일이 있는데, 해당 파일에서 모든 맵의 Default 게임모드를 설정할 수 있다.

개별은 Editor에서~

 

 

[GamsState]

 + GameState에서는 개별 클라이언트에서 게임의 상태를 모니터링할 수 있는 정보들을 입력할 수 있습니다.

즉 GameMode가 게임 전반전인 틀을 설정하는 것이라면, GameState는 현재 돌아가고있는 상태에 대한 정보를 저장하죠.

만약 Player 개개인의 정보를 관리하고싶다면, PlayerState를 이용하는 것이 좋습니다.

GameMode는 Server에서만 관리하지만, GameStateServer와 Client들과 정보를 동기화해서 관리합니다.

해당 기능을 위한 대표적인 변수/함수를보면


GetServerWorldTimeSeconds

 - UWorld함수의 GetTimeSeconds의 서버버전으로, 서버와 클라간의 동기화된 시간으로 많이 사용한다.

PlayerArray

 - 모든 APlayerState오브젝트에 대한 배열로, 게임 플레이어들에게 어떤 작업을 할 때 유용하다.

HasBegunPlay

 - 특정 Game Actor가 BeginPlay함수를 호출했는지 확인할 때 사용.

 

 + GameMode와 GameState는 서로 짝지어서 동작하기 때문에, 특정 GameMode를 만들더라도 해당 모드에 대한 GameStateAGameStateBase에서 파생되어야합니다.

 

 + C++클래스나 BP에서 많이 확장해서 사용합니다.





Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

 + 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!



퍼포스랑 깃의 차이점이 뭘까?

 + 가장 큰 차이점은 Git은 분산형이라는 것이고 Perforce(이하 P4V)는 중앙집중형이라는 것이다.


 + 이것 말고도 다른 차이점이 있으니, 둘의 차이가 "분산vs중앙집중"이라고 확언하면 안된다.




<선택은?>

 + Git하나의 팀에서 사용하면 좋고, P4V다른 분야의 팀들과 함께할 때 사용하면 좋다.


Git

1) Code-Only Project

2) Small Group

3) Fast Release Cycles

 + 위의 3가지 경우에 해당할 때 Git이 가장 큰 효과를 발휘한다.

 + 대표적인 예로 Website 개발이 있다.


 + 분산형 Git은 자신의 Machine에 소스코드를 다운받아(History까지 있는 풀 버전) 자신의 로컬에서 여러가지 작업을 할 수 있다.

하지만 이 경우(팀원들 각자 repo의 복사본을 가진 경우), "누가 Master가 될 건지?"와 같은 고민이나 repo관리의 어려움 등이 생긴다.

이러한 이유 때문에 요즘 많은 팀들이 중앙집중형 Git을 사용한다.

이런 형태는 Pull Request를 통해 프로젝트의 변경점을 Master Branch에 적용하며, 특정 개발자의 작업공간이 아닌 Dedicated Git Server에서 작업된다.


 + Git의 권한은 repo 단계에서 할당되는데, 이로인해 보안 요건을 갖춘 팀은 프로젝트를 여러 저장소로 분리한 뒤, 각각의 작업하는 저장소에 맞게 개발자들에게 권한을 할당해서 프로젝트를 진행한다.

이렇게하면 각 저장소에 대한 감시는 쉬워지는데, 하나의 프로젝트를 여러 저장소로 나누면서 각 저장소들간의 상호의존성 문제를 처리해야한다.

( 조금 이해해보자면, 다른 저장소끼리 어떻게 코드를 적용시켜 하나의 Patch를 적용시킬 것이냐? 를 해결하는 것이라 보면 될듯? )

 = 참고 : https://www.mediawiki.org/wiki/Gerrit/Cross-repo_dependencies


P4V

1) Complex Project with various digital assets.

2) Large Group

 + 위의 2가지 경우라면 P4V가 큰 효과를 발휘한다.

 + 대표적인 예로 여러 Binary 파일이나 Design 파일을 쓰는 Game이나 반도체 개발이 있다.


 + P4V는 중앙집중형으로, 모든 개발자가 최신 버전을 가질 수 있게 하나의 저장소에 모든것을 저장한다. 그들이 어디다 작업하던, 모든 커밋은 중앙서버에 적용된다.

그러면서 신뢰도있는 프로젝트 소스를 가질 수 있다.

하나의 공간에서 모든 변화를 확인한다는 것은 작업자들이 프로젝트의 진행상황을 쉽게 확인할 수 있으며, 그로인해 서로 간의 소통이 활성화된다. 

어떤 작업을 하던 일단 로컬에 저장된다.

중앙집중형은 코드를 조화롭고 재사용하기 쉽게 만들고 코드에 대한 검사와 추적도 확실하게 할 수 있다.




<Performance>

Git!

 + 로컬 Commits, Diffs, merges 는 깃이 빠르다. 하지만 Push와 Pull을 사용하는 개발자가 많을수록 퍼포먼스는 떨어지며 생산성도 떨어진다. 즉, 서버 이용률이 많아지면 많아질수록 생산성이 떨어진다.


P4V!

 + Helix Core는 스피드와 스케일을 위해 만들어졌기에, 하루에 백만 이상의 드렌젝션, 10억 단위의 파일들, 페타바이트(1024테라바이트) 단위의 용량을 가질 수 있다. 

 + 개발자는 그들의 워크스테이션 파일들이 최신화 되었는지 빠르고 쉽게 확인가능하고 바이너리파일 같은 경우도 독점적인 Lock을 걸어서 다룰 수 있다. (이걸 CheckOut이라고 부르는데, 다른 사람들과 작업의 Step이 엉킬 일을 방지한다.)

그리고 PFA(Perforce Federated Architecture)라는게 있는데, 로컬에서 큰용량의 Clone/pull/build 작업 성능을 빠르게 해준다.

 * Helix Core - P4V의 중앙 서버. P4V가 있고 그 내부에 Helix Core가 있다.




<Managing Large Files/Binaries>

 + 개발하면서 큰 파일이나 바이너리 아티펙트들은 나오기 마련. 그것들은 빌드나 테스팅의 인풋/아웃풋으로 나올 수 있는데, 게임개발같은 경우, 이건 피할 수 없는 부분이다. 최종 결과물을 위해 개발자와 아티스트는 이걸 통합할 필요가있다.


Git!

 + 요즘 깃은 LFS(Large File Storage)를 이용해서 관리한다. 근데 대부분의 큰 팀들은 Nexus나 Artifactory같은 아티팩트 레포지토리 툴을 사용해 많은 양의 바이너리 에셋을 관리한다.

이는 더 이상 Single Source of truth (하나의 소스라는 믿음?)를 가질 수 없고, 추가적인 툴로인해 빌드 파이프라인이 복잡해진다는 것을 의미한다.


P4V!

 + Helix Core에서는 모두 하나의 장소에 저장할 수 있다. 아티펙트들도 소스코드처럼 Check Out을 통해 변경점을 관리할 수 있다. Check Out을하면 다른 사람이 해당 파일을 Submit하거나 작업할 수 없음! 그로인해 작업은 굉장히 단순해진다. 그래서 관리자는 서드파티나 플러그인들의 라이센스나 소스코드와 아티펙트들의 통합을 관리할 필요가 없음.




<Branching>

 + Git이나 P4V는 가벼운 Branching을 제공한다. 비록, Branching이 힘들어도...


Git!

 + Git은 언제든지 사용자가 원하면 새로운 Branch를 생성해서 관리할 수 있다. 각각의 브랜치에 변경점을 커밋하고 머지하고 rebase할 수 있다. 하지만 로컬의 마스터는 항상 최신화가 되어있지 않아서 항상 중앙 repo에서 최신 데이터를 가져와야한다. 그렇지않으면, 개발자가 많아질 수록 변경점이 많아지고 그로인해 충돌도 많이 발생하기 때문. 이걸로 인해 잡아먹히는 시간이 많다!

또 만약 cross repository dependencies를 가지고 있다면, repo사이의 충돌까지 처리해야하는데... 이건 팀 작업을 정말 힘들게 만든다.


P4V!

 + Helix Core는... 파일 계층별로 브랜치가 나눠진다고 볼 수 있다. 원하는 파일을 골라서 체크아웃하고 서밋하면된다. 상호 배타적인 레크아웃은 다른 사람이 어떤 작업을 하고있는지 눈으로 확인할 수 있다. 파일단위까지 내려온 세부적인 권한은 관리자가 중요한 파일을 계속해서 유지할 수 있게 한다.


 + 퍼포스도 브랜치와 머지를 할 수 있는 방법인 Perforce Stream이라는게 있는데, 이것은 워크스페이스 셋업을 단순하게한다. 개발자는 쉽게 Stream을 바꿀 수 있고 변경점이 전파되는 방법을 쉽게 볼 수 있다. Git처럼 마스터 스트림에 서밋할 때 충돌이 발생할 수 있는데, Helix Core의 장점인 작업과정을 볼수 있는 것잠재적인 머지 충돌을 사전에 알 수 있는 것으로 쉽게 관리된다.

(아직은 잘 모르겠는데, 충돌 가능성을 미리 확인할 수 있나벼?)

게다가 Helix Core는 확장성이 좋아 다양한 컴포넌트에 영향을 줄정도의 많은 변경점을 한 번에 서밋해도 문제없다.

이건 코드 dependency의 이슈를 상당히 줄여줄 수 있다. 이것도 깃처럼 cross repository dependencies가 일어날 수 있는데, 역시나 쉽게 추척하고 관리할 수 있다.




<So Why Use Git?>

Git!

 + Git은 가장 기본적인 VCS(Version Control System)로, 로컬에서는 진짜 빠르다. 그리고 많이 사용되기 때문에 VCS를 처음 사용할 때, Git을 많이 사용한다. 그리고... 공짜다!

 + 최근 몇 년동안 여러 기업들이 오픈소스 SW를 자본화하려고 많이 노력했으며, GitHub, GitLab, Atlassian(Source Tree)이 대표적인 SW 또는 기업이다.

이것들은 Git에서 좋은 유저 인터페이스나 코드리뷰 workflows, 대용량의 repo를 수용하고 관리하거나 pipeline통합을 가능하게 했다.

대부분의 Git제공자들은 기업보다 개인이나 무료 사용자들한테 더 유명한데, 그 이유는 대용량이나 여러 artifacts들을 관리하기 어려운 구조로 되어있기 때문이다. (현재는 그것을 해결하기 위해 LFS 등의 기능을 제공한다.)


P4V!

 + When to Use Perforce(Helix Core)

 - 대용량의 code base

 - Binary나 그래픽 소스같은 Non-code assets, artifacts

 - 코드 종속성을 줄이기 위해

 - 큰 규모이거나 다양한 분야가 존재하는 팀들.




결론 : 둘 중에 고민할 필요 전혀 없음!

 + 요즘은 Git을쓰냐 P4V를 쓰냐 싸울 필요가 없다.


 + Git도 P4V의 장점을 가져가고있고, P4V에서도 Git을 연동해서 사용할 수 있다.

Helix4Git에서 이게 가능한데, 기존의 Git Command를 이용해서 작업할 수 있으며, HelixCore server를 사용하기에 기존 다른 것들보다 더 빠른 Git성능을 가질 수 있다.


 + 특히 CI/CD(Continuous Integratioin / Continuous Delivery 지속적인 통합, 배포?)팀에서 빠른 피드백을 받을 수 있어, 프로젝트 전체 진행속도를 빠르게 할 수 있다.





Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

+ Recent posts