본문 바로가기

SSE2를 이용한 Vector, Matrix 구축 SSE2? SSE2는 SIMD 명령어 집합 중에 하나로, 2001년에 처음 공개되었다. 그 후에도 SSE3, 4와 AVX 등의 다양한 명령어 집합이 발표되었다. 그중에서 SSE2를 선택한 가장 큰 이유는 128비트 레지스터와 활용에 필요한 명령어가 있고, 거의 모든 컴퓨터가 지원하는 명령어 집합이기 때문이다. 물론 추후 다른 명령어 집합으로 확장할 수 있게끔 구축하였다. 어떻게 구축하였는지 역시 뒤에 설명되어있다. SIMD 명령어와 Vector, Matrix의 분리 가장 중요한 부분이다. SIMD 명령어를 분리하면 추후 다른 명령어 집합으로 확장해도 Vector, Matrix에는 영향을 주지 않게 된다. 또한 SIMD 명령어의 최적화를 위해서는 Load, Store를 최대한 줄이고 적재되어있는 상태에서 ..
현대 컴파일러에서의 inline 함수 inline 키워드는 inlining과 관련이 없다 일단 inline의 정의부터 확실히 하자. inline은 컴파일러에게 해당 함수의 inlining을 요청하는 함수이다. 강요가 아니다. 그렇기에 __forceinline 등의 inlining을 강요하는 키워드가 있다. 그러나 요즘의 컴파일러는 똑똑해서 자체적으로 inlining 여부를 판단한다. 즉 inline 키워드는 inlining과 관련이 없다. inline 키워드의 의의 그럼 inline 키워드는 쓸 이유가 없을까? 그건 아니다. inline 키워드는 해당 함수가 ODR을 무시하게 만들어준다. ODR은 One Definition Rule의 약자로, 객체나 함수의 정의는 유일해야한다.라는 규칙이다. 이 때문에 선언은 헤더에, 정의는 cpp 파일에 ..
Random의 객체 기반 설계 객체 기반 Random이 필요한 이유 기존에 사용하던 C언어의 rand(), srand()와 UE4의 Random(Random Stream 제외)은 전역 State 기반 랜덤이다. 그렇기에 어디서 난수를 뽑더라도 그것이 다른 곳에 영향을 미치게 된다. 이는 특히 네트워크 환경에서 난수를 동기화하거나, 멀티 스레드 환경에서 프로젝트를 진행할 때 문제가 된다. 이를 객체 기반으로 하면 해결할 수 있다. 객체의 시드만 맞춰주면 다른 객체에 영향을 주고받지 않으면서 원하는 난수를 얻을 수 있다. 그리고 객체로 하면 Engine과 Distributor를 자유롭게 설정할 수 있다는 장점이 존재한다. 구현 코드와 함께 보도록 하자. 단순히 보면 C++ 11의 random 객체를 wrapping 한 것이긴 하다. T는..
CMake, Google Test, Github Action을 통한 테스트 자동화 테스트의 필요성 BSMath는 Header-Only Library이다. 또한 템플릿이 굉장히 많이 사용되었다. 그렇기에 테스트가 정상적으로 수행되는가 이전에, 테스트 코드가 컴파일이 되는가만 보아도 많은 에러를 고칠 수 있다. 그렇기에 테스트를 프로젝트에 도입하게 되었다. CMake CMake란? CMake는 한마디로 요약하면 Multi-Platform Meta Make이다. 기존의 make를 통해서도 빌드는 가능하지만, 이를 추상화하여 간단하게 빌드 스크립트를 작성할 수 있다. 무엇보다도 CMake는 Windows 환경에서 수행 시 Solution 파일을 생성하는 등 다양한 플랫폼에서 동작한다. 그렇기에 프로젝트의 크기는 작지만, 개발은 Windows에서, 테스트는 Linux 환경에서 수행하는 BSMa..
Memorize: RECALL 개발 기간: 2020.05.20 ~ 2020.09.21 (4개월) 개인 프로젝트 장르: 오픈월드 액션 RPG 게임 개발 환경: UE4, C++, Blueprint 특징 약 공격, 강 공격이 구분되며, 이를 통해 콤보를 이어나갈 수 있다. 특정한 콤보를 진행할 경우 스킬이 발동된다. 무기를 3개 휴대하고 실시간으로 변경 가능하다. 전투 중에 무기를 변경하며 콤보를 이어나갈 수 있다. 멀티플레이가 가능하게끔 제작되었으며, 추후 Co-op 기능 추가 예정 Github: https://github.com/blAs1N/Memorize-RECALL
Binary Tree를 이용한 콤보 시스템 구현 왜 Binary Tree인가? Memorize: RECALL의 특징 중 하나는 약 공격과 강 공격을 이용한 콤보 시스템이다. 또한 특정 콤보를 만족하면 일반적으로 실행되는 공격 대신 특수한 스킬이 실행된다. 이를 만족하는 구현을 위해 Binary Tree를 사용했다. 약 공격은 좌측 자식 노드, 강 공격은 우측 자식 노드로 가게 하면 설정해둔 Tree를 통해 적절한 Skill이 실행될 것이기 때문이다. Binary Tree 설정 Skill Class 설정 무기를 교체해도 콤보 진행은 유지되기에 Binary Tree는 Weapon에, Iterator는 Weapon Component에 존재한다. 우선 Weapon에 있는 Skill Class의 설정 코드를 보면, 우선 Data Table에 있는 Combo H..
Key 값을 이용한 Character, Weapon, Skill 데이터 관리 Key를 사용한 이유 처음에는 직접 Mesh와 Animation, Transform을 설정해주었다. 그러나 하나의 프로퍼티를 변경할 때마다 모든 값을 그에 맞추는 것은 번거로운 작업이었고, 그 값을 매번 기억하는 것 역시 비효율적이었다. 그래서 DataTable에 값을 저장한 후, 키 값을 변경하면 그에 맞추어 자동으로 변경되게끔 제작하였다. 또한 젤다의 전설: BOTW와 비슷하게 같은 무기의 같은 스킬도 레벨에 따라서 다른 효과를 입히도록 만들기 위해 Level 시스템을 도입했다. 그렇기에 Weapon에 Skill의 클래스는 직접 저장할 수 있더라도, Skill의 Data는 직접 저장하지 못하고 DB처럼 값을 기반으로 찾아올 필요가 있었다. 이를 구현하기 위해 Weapon의 키, Level, Skill..
Editor Time에 Character와 Weapon 교체하기 Editor Time 변경이 필요한 이유 Player Character의 블루프린트나, 맵에 배치된 AI들의 프로퍼티만을 변경해도 Editor에서 바로 적용되게끔 하고 싶었다. 변경 즉시 피드백이 되어야 올바르게 변경되었는지 확인할 수 있기 때문이다. 물론 Skill Data 같은 Non-Visual적인 객체들은 Editor Time에 변경할 필요가 없다. 즉 Character와 Weapon의 키 값만 Editor Time에 확인하여 키 값에 맞게 교체하면 된다. 프로퍼티 변경을 인식하는 방법 UObject의 수많은 Virtual 함수 중에 PostEditChangeProperty라는 함수가 있다. 프로퍼티가 변경된 후 호출되는 함수로 이를 이용해서 Editor Time 변경이 가능하다. 또한 #WITH..