묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Memory Pool #1에서 Memory 생성자에서 반복문 수정 사항!
다음처럼 하면 의도대로 동작합니다!int32 size = 0; // _poolTable이 4097 크기인 이유는 요구 사이즈가 1부터 시작해서 4096까지 가야 하므로 int32 table_index = 1; for (size = 32; size < 1024; size += 32) { MemoryPool* pool = new MemoryPool(size); _pools.push_back(pool); while (table_index <= size) { _pool_table[table_index] = pool; ++table_index; } } for (; size < 2048; size += 128) { MemoryPool* pool = new MemoryPool(size); _pools.push_back(pool); while (table_index <= size) { _pool_table[table_index] = pool; ++table_index; } } for (; size <= 4098; size += 256) { MemoryPool* pool = new MemoryPool(size); _pools.push_back(pool); while (table_index <= size) { _pool_table[table_index] = pool; ++table_index; } } 반복문의 조건문에서 등호(=)를 빼면 됩니다. 경계의 값은 다음 반복문에서 처리할 수 있으니까요. 마지막 반복문은 다음 반복문에서 처리할 게 없으므로 끝까지 가야 해서 등호를 살려놓습니다.예를 들어 두 번째 반복문에서, table_size는 이전 반복문에서 1024가 되고, 두 번째 반복문의 size는 1024부터 시작하니까 아귀가 딱딱 맞게 돼요. 경계값에 문제 없는 것도 확인했습니다. 약간 갸우뚱하셨던 분들은 참고하면 좋을 것 같습니다!
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
PopLock 호출과 관련된 질문입니다.
특정 lock L1이 pop되는 상황이 있다고 할 때 L1으로의 순방향 간선 정보가 담긴 다른 Lock들의 history에 대해서는 별도로 L1값을 제거해야 할 필요는 없나요??
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
난생 처음 보는 동작인데 visual studio2022 버그일려나요. 도저히 이유를 모르겠습니다.
Missile 클래스에서 WraithRef _target = nullptr; 코드를 넣어주면, GameServer.cpp에서 테스트할 때 MissileRef missile(new Missile()); 이 코드를 타고 들어가면 TSharedPtr(T* ptr) { Set(ptr); } 동작할 때 ptr에 nullptr이 들어옵니다.Missile 클래스에서 WraithRef _target = nullptr;을 하지 않고 Missile 클래스에서 WraithRef _target; 으로만 작성하면 정상 동작하고요.저와 같은 증상 겪는 분 없나요? vs 버전은 17.10.4 입니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
데드락 탐지에서 강의 극후반에 LLockStack 관련한 질문입니다!
안녕하세요.나중에 프로젝트 진행하실 땐 lock stack을 TLS로 관리해서 스레드마다 스레드 id가 관리되도록 하신다 말씀하셨습니다. 여기에서 생긴 궁금증입니다. 스레드 id가 부여될 때, 감소하지 않고 증가하는 nameToId().size()로 만들어지는 이상 모든 id가 고유할 거라고 생각합니다.id를 통해서 lockHistory에서 value(set객체)를 꺼냅니다. lockHistory는 TLS에서 관리되지 않는 전역 객체입니다(애초에 그러면 안 되겠죠. 전역적으로 사이클 여부를 탐지해야 하니까요!).스레드 id가 유일한 이상 lockStack을 TLS에서 관리하나 전역으로 관리하는 것이 차이가 없을 것 같은데, 강의 후반에 새로 영상을 추가하시어 '스레드마다 잡고 있는 락이 다르기 때문에 TLS로 관리해야 한다'고 말씀하신 이유가 궁금합니다!id가 전역적으로 1,2,3,4,5,6..이렇게 증가하거나 스레드 별 공간에서 {1,2..} {1,2...} {1,2...} 의 차이 정도로만 생각되어 어떤 본질적인 차이가 있는지 알고 싶습니다!p.s 수업에서 진행한 테스트 코드에서도 문제가 없었던 이유도 궁금증에 한몫을 했습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Reader/Writer-Lock 강의 다 듣고 제가 제대로 이해한 게 맞는지 확인받고 싶습니다!
안녕하세요!어제, 강의도 다 안 듣고 질문을 드린 바보 같은 저를 질책하며 강의를 다 듣고 제가 이해한 게 맞는지 확인을 좀 받고 싶습니다!락 획득 정책을 말씀하실 때 살짝 이해가 안 가는 부분이 있었는데 동일 스레드일 때란 걸 알게 되고 나서는 이해에 큰 어려움이 없었습니다. 그래도 확인이 필요하다는 생각이 들었습니다! 각 항목을 번호로 구분해보겠습니다!동일 스레드일 때의 정책이란 게 락을 획득 후 실행될 때는 사실상 싱글 스레드인 것처럼 생각해도 되겠더라구요그렇다고 한다면 GameServer.cpp에서 테스트 코드 작성하실 때 ThreadWrite()일 때 TestPush(), TestPop()의 동작이 한 스레드에서 동작하는 건 당연히 문제가 안 되니까 W->W 혹은 W->R을 허용하는 게 이해가 됐습니다. 한 처리가 완료되고 나서 다른 처리로 넘어가니까요.그렇다면 같은 논리가 적용될 것 같은데 R->W은 왜 안 되느냐에 대해서도 생각해봤는데요. 논리적으로 접근했을 때, 하나의 함수 내에서 읽기 연산 중에 쓰기 연산을 하는 건 단일 책임 원칙에도 위반될 뿐더러 이상한 코드가 나오더라고요. 가령 테스트 코드로 작성하신 TestRead() 안에 TestPush() 혹은 TestPop()을 넣어버리면 안 되니까요. 또한 데드락이 생기지 않기 위해서는 락을 거는 순서가 중요한데, w->r을 허용한 이상 r->w를 허용하면 데드락이 생기기 딱 좋다.ReadLock에 대해서는, WriteLock을 잡고 있지 않은 다른 스레드는 ReadLock을 획득할 수 있다!ReadLock의 주석에 "아무도 소유하고 있지 않을 때"라고 되어 있어서, 조금 헷갈렸는데요. 코드를 보면 마스킹해서 read_count만 확인하는 걸 보고 역시 ReadLock은 WriteLock을 잡고 있지 않은 스레드도 잡을 수 있구나, 카운트 올리는 것만 경합하는 거구나, 로 이해했습니다.2년 전에 처음 강의를 들을 때 제대로 이해 안 하고 넘어갔다가 나중에 큰 화를 당했어서, 이번에는 확실히 이해하려고 하다 보니 코드에서 참 얻을 게 많다 느낍니다. 틀린 게 있으면 지적 부탁드립니다. 감사합니다!
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part9: MMO 컨텐츠 구현 (DB연동 + 대형 구조 + 라이브 준비)
코드변경을 하면 오류가 생기는데요
코드를 조금만 바꿔도 체력이 0으로 변경되고 화살이 캐릭터 스폰 장소에서 캐릭터가 움직인 장소로 갔다가 몬스터에게 향하게 되는데 어디를 봐야 해결할 수 있을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Reader/Writer 강의에서 마스킹 관련한 질문입니다!
안녕하세요!아직 끝까진 들은 건 아니지만 중간에 큰 의문점이 생겨서 질문드립니다.32형 변수에 상위 비트, 하위 비트를 사용하려면 | 연산을 이용해야 하지 않나요~?가령 상위 비트에 새로운 값을 쓰는 걸 의사 코드로 표현하면,int flag = _lockFlag.load();desired = (flag & 0x0000FFFF) | ((LThreadId << 16) & WRITE_THREAD_MASK);이렇게 하지 않고 다음 코드를 돌리면while (true) { for (int spin_count = 0; spin_count < MAX_SPIN_COUNT; ++spin_count) { uint32 expected = EMPTY_FLAG; if (_lock_flag.compare_exchange_strong(OUT expected, desired)) { ++_write_count; return; } } }write flag를 쓸 때마다 read flag가 날아가는 것 같아서요!
-
미해결[켠김에 출시까지] 유니티 방치형 키우기 게임 (M1 + C1)
다운 받은 맵 프리팹을 오픈해보니 핑크색으로 보이네요
구글링을 해보니 shader 문제라고 하는데 세팅하는 방법이 있을까요?2022.3.45f1 lts 버전입니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Lock-Free Stack #2 01:16쯤에 말씀하신 동시에 TryPop() 할 경우..질문입니다.
안녕하세요!동시에 TryPop() 을 할 경우, oldHead를 참조하는 스레드가 있을 수 있고 이 때 무작정 해제해버리면 use after delete 오류가 발생할 수 있다고 하셨습니다.TryDelete() 함수를 구현하실 때, 1 == popCount 안에서 delete old_head 를 할 때는 이미 분리했으니까 괜찮다고 하셨는데요. 첫 문단에서 언급한 부분과 반대되는 말을 하신 것 같다는 느낌을 받았습니다.제가 생각했을 때는, 저희 수업 때 사용하신 예제 코드에서는, cas 연산을 통해 oldHead 를 분리했기 때문에 use after delete 오류가 안 날 것 같단 생각이 들더라고요.궁금해서 테스트를 해봤습니다.TryDelete() 함수를 호출하지 않고 바로 delete old_head; 를 호출하는 코드를 넣었고요, 지금 이 질문을 올리고 있는 와중에 push() 는 sleep_for(1ms)를 주고 pop()을 하는 스레드는 5개를 돌려서, 진단 도구에서 확인되는 프로세스 메모리가 1mb이 유지되게 설정해서 30분 넘게 돌려보고 있습니다. 오류가 안 나고 있는 광경을 목격 중입니다. 그냥 운이 좋은 걸까요?오류가 발생하지 않는 이유는 다음과 같다 생각합니다.atomic 변수인 head에서 cas 연산을 하기 때문에 간발의 차이로 먼저 다음 코드를 통과한 스레드가 획득한 oldHead는 다른 스레드가 이후에 될 oldHead와 같지 않다. while 조건에서 true를 반환하는 순간 head는 head의 next를 가리키고 있게 되기 때문이다. compare_exchange_weak() 함수가 true를 반환하면 head는 원자적으로 head->next를 가리키는 상태가 된다.while (old && false == _head.compare_exchange_weak(old, old->next)) return false; 고견 부탁드립니다.멋진 강의 감사합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강의를 듣던중에 궁금한점이 생겨서 질문드립니다.
Reader-Writer Lock 구현중에 Atomic 변수를 사용하고 있는데, Atomic 변수자체가 lock이 포함되어 있어서 대규모 Read가 병렬적으로 처리되는 상황이 아니라면 일반 lock을 사용하는 것이 더 효율이 좋을 것 같습니다.하지만 Reader-Writer Lock이 의미가 있을 정도로 대규모 Read가 빈번하게 일어나는 경우에는 WriteLock쪽에서 기아 현상이 발생할 것 같습니다.그렇다면 Reader-Writer Lock은 피크 타임에 대규모 Read가 발생하는 경우에만 사용하는 건가요?(LThreadId << 16) & WRITE_THREAD_MASK 부분에서 굳이 & 연산을 추가로 하는 이유가 뭔가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
식별자 및 헤더 에러
2022버전인데정의는 되어있으나 특정 tcp/ip함수들을 식별하지 못하는 현상이 있습니다.(헤더가드 다 하였음)제 경우에는 inet_ntop 함수 단 하나만 컴파일러가 식별하지못하는 에러가있어서 stackoverflow나 reddit을 찾아도 원하는 상황에 및 해결법은 나오지않아pch.h환경에서 쓰기때문에 GlobalPch.h 에서#include <WinSock2.h>#include <mswsock.h>#include <ws2tcpip.h>#include <windows.h>4가지 헤더를 이 순서대로 배치하고 프로젝트 별 헤더에서는 위의 4가지를 선언하지않으니 해결되었습니다.혹시나 특정함수 단 하나만 식별되지않거나하면 시도 해보시기 바랍니다.저는 시간날렸어도 누군가는 금방 해결해서 다음step으로 빠르게 가길 빕니다.
-
미해결[켠김에 출시까지] 유니티 캐주얼 모바일 MMORPG (M2)
몬스터 AI
안녕하세요 강의 잘 보고 있습니다.현재 3d 모바일 게임을 만들고 있습니다 가상 조이스틱을 이용해 플레이어를 이동시키고 있구요현재 몬스터 AI를 구현하기 위해 A*를 이용해서 PathFinding을 구현중에 있습니다 구현을 위해 맵은 1X1단위로 위에서 아래로 Ray를 쏴서 맵 정보를 저장해 놓은 상태입니다. 이런 상황에서 만약 몬스터는 (2, 0, 2)좌표에 Target은 (5.5, 0, 5.5) 좌표에 있다면 절대 Target을 찾을 수 없겠다 싶어 거리가 1이하이면 찾은걸로 가정을 하려 했습니다 그런데 그 사이에 장애물이 있을 수도 있고 별의 별 상황이 있겠다 싶어 이게 맞는건지 의문이 듭니다 이런 그리드 단위로 움직이지 않는 게임에선 어떻게 Finding을 해야 좋을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
스핀 락에서 CPU 점유율 관련한 질문입니다!
안녕하세요!스핀이 계속 되면서 CPU 점유율이 치솟는 문제에 대한 대안으로 sleep_for(1ms)를 호출하는 건 어떻게 생각하실지 궁금합니다.질문을 다 하고 나니, 커널의 도움을 굳이 받지 않고 오래 대기하지 않아도 되는 상황이 보장될 때 사용하면 좋은 락이 스핀 락인데 sleep_for()을 하면 컨텍스트 스위칭이 발생하겠네요. 이렇게 되면 스핀 락을 쓰는 이유가 퇴색될 것 같다는 생각이 듭니다.고견 부탁드립니다🙏
-
미해결[켠김에 출시까지] 유니티 캐주얼 모바일 MMORPG (M2)
웹서버로 구현되는 기능들이 궁굼합니다.
안녕하세요! 선생님 강의를 거의 빠짐없이 듣고 열심히 공부하고 있는 수강생입니다. MMORPG 개발 9개 시리즈부터 번외편, M1 강의까지 2~3회씩 반복해서 수강하며, 이제는 새로 올라오는 M2 강의를 매주 주말마다 기다리고 있습니다!강의를 기다리며 채팅 기능, 길드, 파티, 우편 시스템을 직접 구현해보려고 하는데, 처음으로 강의 내용과 다른 것을 시도하다 보니 제가 제대로 하고 있는지 확신이 들지 않더라고요. 제가 생각하기에 채팅, 길드, 파티, 우편 기능은 ACCOUNT 서버처럼 WEB 서버로 구현하는 게 좋을 것 같아서, MMORPG 시리즈에서 배운 WEB 서버를 기반으로 위에 기능들을 하나씩 만들어가고 있습니다.서론이 길었네요 ㅠㅠ 궁금한 점이 있습니다! 실제 현업에서는 위에 언급한 기능들이 웹 서버로 구현되는지 아니면 게임 서버로 구현되는지 궁굼합니다!
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
소멸자 부분에서 ref 변수들을 release 하는건 좋지 못한가요?
이번 강의는 순환 참조일 때 한 객체가 소멸될 시 참조하고있는 객체에 관해 refCount가 줄지않아 문제가 생기는 것에 관해서 여러 방법을 알려주시는것 같았습니다. 그렇다면 소멸자 부분에서 자신이 참조하고 있는 객체들을 release해주는것은 어떤가요?참조하는 객체가 많으면 유지보수하기 어려울것 같은데 그래도 이것 또한 해결책이 될 수 있나요?
-
미해결[켠김에 출시까지] 유니티 캐주얼 모바일 MMORPG (M2)
C++강의 듣다가 왔습니다.
C++과 언리얼로 만드는 mmorpg 시리즈를 구매한 학생입니다. 1주차부터 이해가 안돼서찾아보니 Part3 유니티 (클라 프레임워크)Part4 게임서버 (서버 프레임워크 ServerCore)Part7 게임서버&클라 연동 (클라 서버 연동 기본기)Part8 EF Core (ORM) 를 읽어보면 이해하기 쉽다고 하셨는데part4. 게임서버는 C++강의로 들어도 괜찮을까요??
-
미해결[켠김에 출시까지] 유니티 캐주얼 모바일 MMORPG (M2)
멀티 스레드 관련 의문점
안녕하세요 강의 잘 보고 있습니다.코드를 보면서 멀티 스레드 관련해서 궁금한게 있어 질문 남깁니다.1.ClientSession에서 Lock을 잡지 않는 이유는 Receive쪽에서 하나의 스레드만 들어오기(낚시대 비유) 때문에 안걸어도 되는건가요? 즉 하나의 스레드가 메서드 안의 메서드를 타고 타고 들어와서 안전한건가요?2. 1번이 맞다면 ClientSession 에서 GameLogic Push 하는 이유는 스레드 안전성 때문이라기보단 멀티 스레드를 활용하기 위함이라 보면 될까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
writeCount는 원자성 보장하지 않아도 되나요??
writeCount는 atomic이 아닌 일반 uint16이고writeLock++;writeLock--;같은 증감 연산자를 할 때 따로 임계구역 만들지 않는것 처럼 보입니다. 이러면 진짜 만약에 두 개 이상의 쓰레드가 동시에 증감연산을 하게될 경우 이전에 해봤던 예제처럼uint16 temp = writeLock;temp++;writeLock = temp;이렇게 3단으로 실행이 되서 조금씩 오차가 생길 수 있을것 같은데 이 부분은 따로 고려하지 않아도 충분한가요??
-
미해결[켠김에 출시까지] 유니티 캐주얼 모바일 MMORPG (M2)
포폴용으로 AWS 인스턴스 1개와 탄력적 IP 1개를 항시 켜놔도 비용이 부과될까요?
루키스님 안녕하세요? C# AWS 답변 보고 여기로 와서 클라 입장 공인 IP를 가지고 사설 IP에 접근하는 것 성공했습니다. 아침 답변 감사합니다. 제가 포트폴리오 작성 간에 데모 프로그램을 준비해보려고 하는데 (기준은 C# 파트7 수강 이후입니다) 첫 번째 방법은 클라, 서버 exe 한폴더에 넣고 .bat 파일 만들고 이거 하나만 실행시키서 서버 실행 -> 클라 실행 순으로 입장시키기 입니다. 그런데 이 방법은 .net이 안깔려 있으면 서버부터 크래시가 나길래 인사담당자나 면접관이 못볼 수도 있겠어서 찜찜해서 두 번째 방법으로 생각한건 AWS입니다. 윈도우 프리티어와 인스턴스 프리사양, 그리고 고정용 IP용 탄력적 IP를 만들어서 항시 켜놓으려고 합니다(보안 정책은 여기 강의처럼다 뚫어놓긴 합니다). 그리고 데모 프로그램은 클라이언트만 제시하는 방법을 생각 중입니다. 이 경우 AWS 서비스가 무료거나 소액이면 해볼만한 방법이라고 생각되는데 둘 중에 어느 방법이 괜찮을지 의견 여쭈고 싶어서 질문 드립니다.
-
해결됨[켠김에 출시까지] 유니티 캐주얼 모바일 MMORPG (M2)
JobTimer 클래스의 우선순위 큐 질문
안녕하세요. JobTimer 클래스에서 사용된 우선순위 큐 관련해서 2가지 궁금한 점이 있습니다.1. 여기서 사용된 우선순위 큐는 최소힙으로 구현된게 맞나요?PriorityQueue.cs 에 작성된 우선순위 큐는 최대힙 이지만, JobTimerElem 구조체를 정의할 때 CompareTo 메서드를 오버라이딩 해서 최소힙을 사용하게끔 수정한 것으로 이해했는데 제대로 이해한게 맞을까요?2. Pop 메서드에서 힙 정렬 과정 질문 PriorityQueue.cs에 작성된 Pop 메서드의 While 문이 힙 정렬을 담당하는 부분으로 이해했습니다.만약 While 문 한 번으로 정렬이 끝나지 않는 경우는 어떡하나요?예를 들어 다음과 같이 저장된 최소 힙의 경우이렇게 While문이 한 번 끝났는데 최솟값인 2가 루트 위치에 있지 않은 경우가 있어서 질문 드립니다.