온라인 환경에서 Arrow, 제거와 발사 시 동기화 문제
388
작성한 질문수 1
안녕하세요 Rookis님.
강의를 모두 완강하고 포트폴리오를 개선하고 있는 중입니다.
강의 중에 화살을 온라인에 추가할 것이라면 Creature와 GameObject 내용을 수정해야 한다고 하셔서 코드 이사는 완료한 상태입니다.
지금 Arrow는 MyPlayer에서 입력을 받고 State와 WeaponType을 체크하면 Player에서 Scene에 Arrow를 스폰해주는 방식으로 알고 있습니다.
이걸 서버에서는 몬스터나 플레이어를 만드는 GameObject::Create 함수를 파줘서 Arrow를 make_shared로 만들어서 발사 처리를 하게 만들었는데요
서버에서 몬스터가 제거되면 클라이언트에서도 정상적으로 몬스터가 제거되는걸 확인은 했습니다.
그러나 문제가 몇 가지 있습니다.
Arrow 스마트 포인터가 해제되지 않는 현상
Arrow 동기화가 종종 씹히는 현상
입니다.
먼저 1번입니다.
make_shared로 생성된 Arrow가 해제되지 않음
void Player::UpdateSkill()
{
if (room == nullptr)
return;
if (info.weapontype() == Protocol::WEAPON_TYPE_SWORD)
{
// 내 앞에 있는 좌표
CreatureRef creature = room->GetCreatureAt(GetFrontCellPos());
if (creature)
{
if (creature->GetType() == Protocol::OBJECT_TYPE_PLAYER)
{
SetState(IDLE);
return;
}
// 몬스터가 플레이어에게 피격
creature->OnDamaged(shared_from_this());
}
}
else if (info.weapontype() == Protocol::WEAPON_TYPE_BOW)
{
ArrowRef arrow = CreateArrow();
arrow->SetDir(GetLookAtDir(GetFrontCellPos()));
arrow->SetOwner(shared_from_this());
arrow->room = room;
arrow->info.set_posx(info.posx());
arrow->info.set_posy(info.posy());
arrow->SetState(IDLE, true);
room->AddObject(arrow);
}
SetState(IDLE);
}서버쪽의 UpdateSkill 함수인데 여기에서 arrow를 CreateArrow로 만들어서 room에 AddObject로 _arrows map을 만들어 관리를 하고 있습니다. (사실 룸에서 발사체를 관리하는 것이 옳은지도 의문이긴 합니다)
void GameRoom::Update()
{
for (auto& item : _players)
{
item.second->Update();
}
for (auto& item : _monsters)
{
item.second->Update();
}
for (auto& item : _arrows)
{
item.second->Tick();
}
}그리고 Update 함수, AddObject, RemoveObject도 _arrows map을 처리하게 만들었습니다.
이렇게 처리하다 보니 화살을 제거할 때 몬스터가 피격받는 순간에 해당 화살을 RemoveObject를 실행하니 삭제 이후에 for문을 돌 때 오류가 발생하며 크래시가 발생했습니다.
Arrow가 _arrows 맵에서 관리되어서 스마트 포인터가 해제가 안되는 것 같은데, 화살을 어떤 때에서 제거해야 될지 모르겠습니다.
지금은 임시적으로 vector에 참조로 받아와서 Update 하단에서 erase하는 방법을 사용하고 있습니다.
화살 동기화 문제
클라이언트에서는 Projectile 클래스에서 _owner에 대한 정보를 들고 있고 Arrow를 Scene에서 소환할 때 GetOwner 함수로 화살의 주인에 대한 포인터를 들고 있도록 했습니다.
기존에 발사할 때도 S_Move 패킷을 그대로 이용해서 Arrow의 _owner 포인터를 이용해서 위치를 초기화해주고 있습니다.
그런데 두 클라이언트를 접속시켜서 2를 눌러 WeaponType을 Bow로 바꿔서 공격 키로 테스트해보면 종종 반대쪽 플레이어의 화살이 안보이는 경우가 있습니다.
여기에 몇 개의 질문이 있는데요
1) 화살을 생성하고 클라이언트에서 패킷을 전송하는 것이 맞는지
2) 맞다면 어떤 정보를 패킷에 담아야 하는지
3) 서버에서는 어떤 처리를 해주어야 하는지
잘 모르겠습니다.
일단은 Make, Handle 함수를 파서 ObjectInfo를 넣어놓긴 했습니다.
하루 종일 코드를 조작해봐도 해결을 못하고 있습니다.. 도와주세요..
답변 2
1
여기부턴 응용이라 스스로 해결을 하셔야 합니다.
Update에서 제거하면 크래시가 나는 문제는
- &가 아닌 복사본으로 업데이트를 돌거나
- 삭제 예약을 해서 모든 Update가 끝나면 일괄적으로 처리해주기
등으로 처리해주시면 됩니다.
스마트 포인터 문제는 shared, weak를 적절히 사용하시면 되겠습니다.
투사체도 당연히 서버측 관리대상입니다.
사실 서버에서는 스폰 패킷만 보내고
이후에는 클라와 서버가 각각 좌표를 따로 계산해서 동기화하는 것이 일반적입니다.
투사체는 그 정도 중요도는 아니기 때문이죠.
하루 종일 코드를 조작해봐도 해결을 못할 수 있지만,
결국 회사에 들어가면 그래도 어떻게든 해결을 해야 합니다.
더더더 고민을 통해 해결하는 습관을 들이셔야 하는데
물론 이게 말이 쉽지 정말 고통스러운건 당연합니다.
저도 일주일씩 헤딩하고 이런 문제가 초반엔 아주 많았지만
그게 다 경험치로 돌아오니 더 고민해보시기 바랍니다
0
안녕하세요, 인프런 AI 인턴입니다.
강의 내용과 관련하여 화살을 처리하는 부분에 대해 질문을 주셨네요. 서버와 클라이언트 간의 화살 동기화 문제와 화살의 생성 및 제거에 대해 어떻게 처리해야 하는지에 대한 질문입니다.
유사한 상황을 해결한 다음의 답변이 도움이 될 것 같습니다. 강사님께서 화살의 서버에서의 이동 처리 방법과 클라이언트와 서버 사이의 화살 동기화에 대한 해결 방법을 제시하고 계십니다.
위 링크에서 강사님께서 제시한 방법들을 확인하시고, 여러분의 프로젝트에 적용해 보시기 바랍니다. 화살의 생성, 이동, 소멸 로직을 서버와 클라이언트에서 어떻게 처리해야 하는지에 대한 가이드를 얻으실 수 있을 겁니다.
도움이 되길 바라며, 추가적인 질문이 있으시면 언제든 게시판을 통해 질문해 주시기 바랍니다.
문제집은 없나요 수업을 어떻게 들어야 할지 모르겠어요
0
106
2
동적배열 Vector의 push_back 함수에서 조건문 질문
0
74
1
디버깅할때 메모리보는법 단축키가 뭐죠??
0
89
1
113-충돌처리 강의에서 22:26 부근의 SetPos()를 적용해도 충돌되지 않고 뚫고 지나가게 됩니다.
0
87
1
SaveFile에서 크래시 발생하는 분들 체크해보세요
1
70
1
수업자료 확인 부탁드립니다.
0
106
3
explicit을 붙였을 때 빨간줄이 뜨는 이유가 맞는지 궁금합니다.
0
100
0
22강에서 구조체와 포인터로 설명해주셨는데 패딩의 경우는 어떻게 되나요?
0
88
2
리소스 매니저 강의 18분 부근
0
89
1
[Service강의] owner -> shared_ptr
0
80
2
C#에서 생성자 관련 질문
0
83
2
특정 조건에서만 함수를 반환할 때
0
90
2
스택 empty
0
105
2
섹션4 배열실습 질문입니다.
0
132
1
섹션3 '파일분할' 강의 질문입니다.
0
99
1
Defines.h의 DECLARE_SINGLE관련 질문입니다.
0
110
1
세션8 우선순위 큐 pop함수의 Predicate 적용 관련 질문이 있습니다.
0
180
3
섹션9 함수 포인터 관련 질문입니다.
0
137
1
exercise_A 번 문제 해결방법에 대한 질문.
0
150
1
[강의명: virtual 소멸자] 자식 클래스의 소멸자에도 virtual 을 붙이시는 이유가 궁금합니다
0
198
2
Scene과 SceneManager 강의 수강 중 키보드 입력 오류
0
146
1
Window API 강의 수강 중 LARGE_INTEGER 타입 변환 오류
0
198
3
섹션15 스마트 포인터 20:00 질문이요!
0
127
1
55강 수업자료 빌드를 하면 이상합니다.
0
132
1





