목록언리얼 엔진 (77)
게임 개발 메모장
. 우리가 사용하는 리슨 서버 구조에서는 서버와 클라이언트가 동일한 어플리케이션을 사용한다. 그렇기 때문에 이 어플리케이션을 구현할 때는 서버와 클라이언트가 같은 코드를 사용해야 되는데 신뢰를 가져야된다. 신뢰를 가져야 하는 액터는 서버에만 존재하기 때문에 게임 플레이에 영향을 미치는 게임 로직은 우리가 서버인지를 파악해서 그 서버에서만 동작하도록 구성을 해줘야 된다. 액터 단위로 이 액터가 신뢰할 수 있는지를 파악할 수 있어야 되는데 이를 위해서 제공하는 것이 언리얼엔진에서는 '역할' 이라는 설정을 제공한다. 현재 동작하는 어플리케이션을 중심으로 해서 이 어플리케이션의 역할을 로컬 역할, 그리고 이 어플레케이션과 커넥션으로 맺어진 원격 어플리케이션의 역할을 리모트 역할이라고 한다. 그리고 오른쪽에 어플..
리스트와 벡터, 어떤게 더 빠를까? 벡터는 연속된 메모리 주소를 가진 Dynamic Array형태의 자료구조이다. 리스트는 힙공간에 값을가진 노드가 생성되어있고, 노드가 다음 인덱스의 또 다른 노드를 가르키는 구조이다. 단편적인 생각으로서는, 리스트와 벡터의 속도 차이에서 가장 큰 차이점은 중간 인덱스에 접근해서 삽입, 삭제를 할때 구조적으로 속도 차이가 날수밖에 없다고 생각하는데, 그렇다면 만약에 리스트와 벡터 둘다 순차적으로 접근할때 어느 자료구조가 더 접근이 빠를까? 배열이나 벡터처럼 연속된 공간으로 구성된 자료구조는 캐시상에서 연속된 공간에 존재하며, 캐시 공간을 차지하는 개수가 적기 때문에 포인터로 연결된 자료구조보다 접근속도가 빠르다. 포인터로 연결된 레코드로 구성된 자료구조(리스트나 트리)는..
FTimerHandle 타입의 변수를 헤더에 먼저 선언하여 전역 변수로 사용한다. GetWorldTimerManager().SetTime 함수를 호출하여, '헤더에 선언한 Timer를 통해 delay 시간 후에 Function 함수를 호출한다.' 라고 정의해주면 된다. 함수를 등록하는건 역시 바인딩을 통해 등록하면 된다. 하지만 코루틴은 시작과 동시에 등록하면, 코루틴 함수에 있는 무한 루프문을 통하여 지속적으로 함수가 호출되지만, 방금 설명한 API는 지속적으로 호출하고 싶다면, 호출된 함수 내에 다시 SetTime 함수를 호출해야 한다. 따지고 보면 코루틴 보다는 '일정 시간 후에 한번만 호출해라.' 는 쪽에 가깝다. 그리고 등록한 함수를 해제하고 싶다면, ClearTimer를 통하여 함수를 등록한 ..
main 안에서 실수로 값을 초기화 해버리는 문제가 생길 수 있는데, 이를 막을 수 있는 방법이 있을까? 정적 멤버 데이터(static member data) - static이 붙은 멤버 데이터 - 모든 객체가 공유한다. - 클래스 내부에 선언을 만들고 클래스 외부에 정의를 만들어야 한다. - 모든 객체가 공유한다. - 멤버 이므로 접근 지정자를 사용할 수 있다. class 내부에 static으로 변수를 선언한다. private로 선언하면 class 내부에서 getter/setter를 통해 해당 변수에 접근이 가능하게 만들 수 있다. class 내부에 static으로 선언된 cnt 값을 c1.getCount()로 호출해 가져올 수 있다. 출력 : 3 정적 멤버 데이터와 일반 멤버 데이터 아래 코드에서 -..
C++에선 런타임에 기초 클래스의 객체 포인터가 어떤 객체를 가리키고 있는지 정보를 알려주는 RTTI 기능을 제공한다. 객체지향에선 클래스 간 상속을 구현할 수 있고, 다형성을 가지게 되어 기초 클래스(Base class)는 자신의 멤버를 위임한 파생 클래스(Derived class)를 자신의 객체 포인터로 가리킬 수 있다. Base *pBase = new Derived(); 하지만 컴파일 당시에는 pBase가 어떤 객체를 가리키고 있는지 알 수 없다. 그저 가상 함수 테이블 vftable에 저장된 함수 주소가 무엇인지에 따라서만 기초 클래스와 파생 클래스 중 어떤 객체를 가리키고 있는지 짐작할 수만 있다. 하지만 그 자체가 정보로 주어지는 것도 아니기 때문에 프로그램은 실행 중에 포인터가 가리키고 있는..
RPC의 기본 개념과 동작 원리 - 원격 프로시저(함수) 호출 - 원격 컴퓨터에 있는 함수를 호출할 수 있도록 만든 통신 프로토콜 - 네트워크 멀티플레이에서 서버와 클라이언트 간에 빠르게 행동을 명령하고 정보를 주고 받는데 사용 - 언리얼 엔진에서 클라이언트에서 서버로 통신하는 유일한 수단을 제공한다. 이 기능의 주요 용도의 속성상 장식이나 휘발성인 비신뢰성 게임플레이 이벤트를 위한것 이는 사운드 재생, 파티클 스폰, 액터의 핵심적인 기능과는 무관한 일시적 효과와 같은 작업을 하는 이벤트를 포함한다. RPC 사용시 OwnerShip 작동 방식을 이해해둬야 한다. 대부분 RPC 실행 장소를 결정하기 때문이다. RPC 사용하기 함수를 RPC 로 선언하려면 UFUNCTION 선언에 Server, Client,..
복합 대입 연산자와 마찬가지로 복합 대입 연산도 가능하도록 할 수 있다. #include using namespace std; class TestClass { public: TestClass() {} ~TestClass() {} //변환 생성자 TestClass(int param) { num = new int; *num = param; } //형변환 허용 operator int() { return *num; } //복합 대입 연산자 TestClass& operator+=(const TestClass& ref) { //현재 값 int* newNum = new int(*num); //누적 값 *newNum += *ref.num; //기존 값 지우고 새 메모리 대체 delete num; num = newNum..
몇 년전에 봤던 영상인데... 추억이 돋는다... 소장각... https://www.youtube.com/watch?v=XVxFoHZXy9U&list=WL&index=20 한 단계씩 코드 실행 : F11 프로시저 단위 실행 : F10 커서의 위치까지 디버깅 진행 : Ctrl + F10 오류메시지가 발생한 줄로 이동 : F4 디버그 중단 : Shift + F5 디버그 다시 시작 : Ctrl + Shift + F5 중단점 설정하기 : F9 모든 중단점 삭제 : Ctrl + Shift + F9 상단의 디버깅 툴바를 사용하셔도 됩니다. 위와 같이 변수에 커서를 가져다 대면 해당 변수가 가지고 있는 값을 확인하실 수 있습니다. 디버그 활용하기 디버그 -> 창으로 가면 다양한 디버깅 창들을 불러내고 활용하실 수 있..
변수뿐만 아니라 클래스나 구조체에서도 단순 대입 연산이 이루어질 수 있다. #include using namespace std; class TestClass { public: TestClass() {} TestClass(int param) { num = new int; *num = param; } TestClass(const TestClass& ref) { num = new int; *num = *ref.num; } ~TestClass() { delete num; } int getNum() { return *num; } private: int *num = nullptr; }; int main() { TestClass a(10); TestClass b(20); a = b;//에러 cout
유저끼리 직접 정보를 주고받을 경우 여러 문제가 있을 수 있기 때문에 중간에 서버를 거쳐서 주고 받는다. P2P 구조는 유저 한명을 임의로 정해서 그 사람 컴퓨터를 서버로 만드는 것. 게임 회사가 서버 비용이 안든다. 서버로 선정된 유저는 ping이 0ms 이 되는 거라 그 사람만 너무 유리하다. ( 1초 = 1000ms ) 요즘 실시간 게임들은 보통 데디케이트 서버를 사용하는데 그냥 클라우드 컴퓨터를 한 대 빌려서 그것을 서버로 운영한다. 그래서 요즘 FPS 게임을 한 판 돌린다고 치면 일단 같은 방에 있는 모든 유저가 AWS 같은 곳에 있는 게임 서버 컴퓨터에 연결이 된다. 그래서 누가 어디로 총을 발사 했고 이런 게임 데이터를 주고 받기 시작하면 이제 게임이 돌아가는 거다. 데이터를 주고 받는법 갑..