• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

화살 쏘는 것을 처리하는 방식

23.04.25 20:55 작성 23.04.25 22:13 수정 조회수 374

0

안녕하세요 루키스님!

제가 루키스님이 강의중 만드신 게임에서 쓰이는 좌표를 float으로 바꾸고 화살이 이동하는 방식을 수정하였습니다.(저는 화살이 아니라 기본 동그라미 이미지의 총알로 사용해봤습니다)

수정 내용은 화살 이동 로직을 처리하는 방법입니다. 기존 로직은 서버에서 GetFrontCellPos 함수를 이용하여 서버에서 이동된 좌표를 클라로 알려줘 이동되는 것으로 알고 있습니다. 클라에서는 UpdateMoving를 통해 움직이고 있구요!

GetFrontCellPos 함수를 활용하여 서버에서 화살을 움직이기에는 좌표 단위가 Int가 아니라 float이니 어떻게 해결 해야할지 고민을 하다가 생각난 방법이 있습니다.

화살을 쏜 후 유니티의 update 문에서 60fps로 서버에 화살이 이동했다는 것을 가르쳐준 후 브로드캐스팅 되게 했습니다. 그 후 서버에서는 받은 패킷에 따라 브로드 캐스팅하게 핸들링 해줬구요.

이제 2명을 접속시키고 화살을 쏴보니 패킷이 밀려서 그런지 몰라도 쐈던 자리로 다시 롤백되는 현상을 발견했습니다(배그에서 트레이서 되는 느낌)

60fps가 너무 자주 요청하는 건가 싶어서 15fps로 돌리니 클라 화면에서 내가 쏜 총알은 똑같이 롤백되면서 총알이 나가지만 다른 Player가 쏜 총알은 롤백이 되지 않았습니다. 하지만 이동된다기 보다는 순간이동 하는 것 처럼 보이기 시작했습니다.

몇가지 실험을 해보니 혼자 접속중일때는 총알이 롤백현상이 일어나지 않고 곧게 잘 날아가는 것을 확인할 수 있으나 인원수가 한 명 늘어나는 순간부터 총알의 롤백 현상이 생기는 것을 확인했습니다. 브로드 캐스팅의 연산량이 늘어나서 패킷이 밀리는 것이 원인인 것 같습니다.

C_SkillMove, S_SkiilMove 라는 패킷을 새로 파주고 실행했습니다.

 

message C_SkillMove{

int32 objectId = 1;

PositionInfo posInfo = 2;

}

message S_SkillMove{

int32 objectId = 1;

PositionInfo posInfo = 2;

}

클라의 업데이트 문에선

if (Time.frameCount % 15== 0)

{

C_SkillMove skillMovePacket = new C_SkillMove();

PosInfo.PosX = transform.position.x;

PosInfo.PosY = transform.position.y;

skillMovePacket.PosInfo = PosInfo;

skillMovePacket.ObjectId = Id;

Managers.Network.Send(skillMovePacket);

}

 

이런 코드로 움직입니다.

 

서버에선

public static void C_SkillMoveHandler(PacketSession session, IMessage packet)

{

C_SkillMove skillMovePacket = packet as C_SkillMove;

ClientSession clientSession = session as ClientSession;

Arrow arrow= ObjectManager.Instance.Find<Arrow >(skillMovePacket.ObjectId);

if (arrow== null)

return;

GameRoom room = arrow.Room;

if (room == null)

return;

room.HandleSkillMove(arrow, skillMovePacket);

}

 

이런식으로 핸들링 하고 HandleSkillMove 함수는

 

public void HandleSkillMove(Arrow arrow, C_SkillMove skillMovePacket)

{

if (arrow == null)

return;

lock (_lock)

{

ObjectInfo info = arrow.Info;

info.PosInfo = skillMovePacket.PosInfo;

S_Move resMovePacket = new S_Move();

resMovePacket.ObjectId = arrow.Info.ObjectId;

resMovePacket.PosInfo = skillMovePacket.PosInfo;

Broadcast(resMovePacket);

}

}

이런 로직으로 움직입니다.

float일 때의 서버에서 이동 처리 방법이 궁금합니다! 또한 위처럼 순간이동되게 가는 것을 방지하는 법도 궁금합니다.. (스르륵 이동하게 처리하는 부분)

 

 

답변 1

답변을 작성해보세요.

0

강의에선 굳이 화살을 위해 추가 코드를 넣지 않았지만
사실 화살은 쐈다는 사실과 소멸만 관리하고,
좌표 관리는 안 하는게 맞습니다!
말씀하신 부분은 클라에서 연산하는 와중에 서버에서 뒤늦게 좌표를 broadcasting해서 그런 것 같네요.

자르트님의 프로필

자르트

질문자

2023.04.26

클라에서 서버로 DirVector 값을 보냈습니다(normalized 해서요!)

그리고 서버에서 위치를 바꿔주게 변경했습니다! 클라에서는 화살을 소환만하고 직접적인 이동은 서버에서 담당합니다!

그런데 끊기면서 순간 이동 하듯이 이동을 합니다... 자연스럽게 이동하는 것 처럼 보이는 방법이 없을까요...ㅠㅠ