유니티 연동 #2

CJB_ny·2022년 3월 8일
0

Unity_Server

목록 보기
53/55
post-thumbnail

그래서 우리가

클라에서 채팅만 받아서 하는게 아니라

이제 플레이어를 움직이거나

하는 그런 간단한 작업을 해보고싶은건데

그래서

정상적인 C#문법으로 이렇게 유니티 오브젝트를 찾으면

if or else 둘중 하나는 찾아야될 것이다.

그래서 Server 구동후 유니티 실행하면

아무것도 안 뜬다! ??

지금 Hello Server가 한번만 뜨고 더이상 뜨지도않고

크래쉬가 난것도 아닌데

이상하다

왜 그럴까..??

이게 왜 안되냐 하면은

메인쓰레드와 관련된 문제라고 볼 수 있다.

우리가 지금까지 만든 네트워크 코드가 어떻게 동작했는지 살펴보면은

패킷을 보낼때랑 받을 때도 마찬가지로

Session에서 이것들을

비동기로 Async계열의 함수를 이용해가지고 비동기로 네트워크 통신을 하고있었다.

그래서 만약 pending이 false라면은 같은애가 실행을 할것인데

만약 true일 경우 멀티쓰레드환경이라 다른 애가 밑에 OnRecvcompleted를 실행 할 수 있다.

그래서

여기서부터는 레드존이다.

그래서 지금 문제가 되는게

메인쓰레드가 네트워크 패킷을 실행하는게 아니라

쓰레드풀에서 놀고있는 다른애가 이것을 실행하고있는것이다.


유니티에서는 게임을 실행하는 쓰레드가 메인쓰레드? 같은 녀석들만 실행을 할 수 있도록 해놨고

쓰레드 풀같은 데서 대리고온애가

이런 게임과 관련된 코드를 실행하는 것을 원천적으로 차단을 해놓은 것이다.

그러니까 이렇게 유니티와 관련된 것에 접근을 하면 안되는것이 핵심적인 내용이다.

그래서 우리가 어떻게든

이녀석을 유니티쪽 쓰레드 즉, 메인 게임 쓰레드에서 실행을 하게끔 조작을 해주어야 한다.

그럼 이 "조작"은 어떻게 해야할지 생각을 해보아야한다.

여기서 바로 처리를 할게 아니라

패킷을 처리를 하기는 할것인데

패킷을 만들어서 바로 Handler로 처리를 할것이 아니라

큐를 만들어서 만든 큐에 집어넣어서 유니티 메인게임 쓰레드가 실행을 할 수 있도록 해주어야 한다.

그래서 packetQueue에다가

싱글톤으로 접근 가능만들고

큐만들기 (Handler에서 넣을 큐임)

그리고 Push, Pop만듦

이렇게하면

메인쓰레드, 백그라운드 쓰레드(네트워크 쓰레드가)

PacketQueue라는 것으로 소통을 하는데

백그라운드 쓰레드가 Push로 밀어 넣고

유니티 메인 쓰레드가 밀어넣은것을 Pop으로 꺼내 쓰는 것이다.

그럼 어디서 Push를 할지가 고민이다.

여기 Handler에서 밀어 넣어 줄 수 있지만

결국에는

여기서 Pop을 해서 Packet번호에 따라 해당 함수를 호출을 해줘야 할텐데

우리가 이때까지 자동화를 만들어놨는데

여기에다 굳이 Handler를 사용하지 않고

packetQueue에다가 밀어 넣는 작업을 하면 슬플 것이다.

백그라운드 쓰레드가 어떻게 일을 처리 하는지 보면은

성공적으로 패킷을 처리를 하면

이곳에 들어와서 밑에 MakePacket으로 패킷을 만들어 준다음에

Handler를 호출해주는 부분까지 해주고 있었다.

그래서 Handler를 바로 호출하지 않고 packetQueue에다가만 넣어놓고 나오고

나중에 실제로 NetWorkManager에서 이것을 꺼내서 Handler쪽에다가 연결을 해줘서

그다음에 PacketHandler쪽으로 호출을 연결을 해주면 굉장히 잘 돌아 갈거같다라는 생각이 든다.

1. Handler, packetQueue 분리 작업

이렇게 분리를 해주도록 하자.

그리고 위에서

이럴 경우 바로 Handler호출을 했는데

MakePacket이 패킷을 반환하도록 만들자.

그래서

T타입으로 반환을 해주자. 그러면 위에서 에러가 뜰텐데

그러면 이제 이녀석 같은 경우에는

Action이 아니라 Func가 되는 것이다.

Func가 delegate이기는 한데

이런식으로 이미

뭔가 정의된 타입이였다.

그리고 Func로 정의할 경우 맨마지막에 out TResult를 넣어줘야한다.

그래서 Func 형식으로

이렇게 바꿔주도록 하자.

그러면 이제 _onRecv는 이제 receive를 한다음에 일련의 과정들이 아니라

이녀석은 말그대로 이제

만들어주는 함수의 역할을 하니까 이제

이름

이렇게 수정을 해주도록 하자.


그리고 이부분도 마찬가지로

이렇게 바꿔주도록 하겠다.

그리고 이름

func로 바꾸는 디테일적인 부분...

그러면

여기서 MakePacketㅇ의 T타입이 IPacket이란게 보장이 되어서

이렇게 받을 수 있다.

여기서 이제 분리를 해놓았으니까

이렇게 호출을 하면 아까와 똑같은 상황이 되는 것이다.

그런데 이제 유니티의 경우에는 == 클라의 경우에는

이부분을 막바로 호출하면 안되고

packetQueue에다가 넣어 놔야 한다.

그래서 여기 인자에 Action옵션을 하나 더 넣어 주도록 하자.

여기다가 이제 옵션으로 어떻게 처리를 할 것인가를 넣어주면은

옵션을 넣어줬다면 넣어준 방식대로 처리를 할 것이고

그게 아니라 default상태라고 하면은

그냥 이렇게 이전과 마찬가지로 HandlePacket을 실행하게끔 해주도록 하자.

그래서 이제 OnRecvPakcet을 어디서 하고있었는지 보면은

ServerSession >

여기서 하는중이였다.

그래서 여기서

바로 패킷을 넘겨주었었는데 이제 여기에서 옵션을 넣어줄 수 있다는 것이다.

여기서 이제 packetQueue에다가 넣어 두라는 작업을 할 것이다.

이렇게하면되는데 여기서 s = session은 굳이 안받아도 되기는 한다.

그리고 참고로 인자가 s, p이렇게 두개가 있는 이유는

OnRecvPacket의 마지막 인자를 보면은

PacketSession, IPacket을 받는 녀석이기때문에 그런것이다.

그래서 우리가 넣어준 방식대로 처리를 해줄 것이니까

유니티에서는


이부분이 호출이 되면서

PacketQueue에다가

Push만 해주게 될 것이다.

그래서 이제 넣어준 녀석을 어디선가는 사용을 해야되는데 (Pop)

이것을 유니티에서 사용하고있는 NetWorkManager같은데서 해주면될 것이다.

이렇게 되면 최종적으로 똑같이

이녀석이 호출되는데 아까와는 다르게 유니티 메인쓰레드가 실행한다.

테스트 해보면

이렇게 잘 뜬다.

백그라운드 쓰레드에서 실행을 했지만 유니티 메인 쓰레드가 실행할 수 있게

큐에다가 잠시 밀어준다음에

유니티메인쓰레드가 실행 할 수 있도록 한 것이다.

지금이게 이렇게하면 한 프레임에

한패킷만 실행이 되겠지만

이것을 이제 조금 조절을 하면 될 것이다.

안에 패킷을 다 비울 때까지

이렇게 해도되고

아니면 일정시간을 줘도 되고

지금은 체팅인데

나중에 움직이는 거든 스킬이든 뭐든

Handler에서 playerId가 몇번인지를 어떻게든 찾아서 실행해주면 될 것이다.


2. PacketFormat 수정

public 붙이기

그리고 이부분 ClientPacketManager에서 수정한 부분이랑 같이 수정 ㄱㄱ(유니티 vs에서)

그리고

이런 부분 수정 ㄱㄱ

이까지 수정하고

PacketGenerator 빌드 ㄱㄱ

그리고 배치파일 ㄱㄱ

그다음 테스트 해보면

잘 돌아간다.

그리고 유니티도 돌려보면 잘 된다.


3. 보내는거 테스트

지금까지는

여기서 패킷을 받아서 까가지고 실행하고있었는데

보내는거도 테스트를 해보도록 하겠다.

1초마다 보내고싶은데 이럴때 가장 유요한게 "코루틴"이라고 했다.

보낼체팅 이렇게 입력하고

이제 보낼려면 추출해야되니까

이렇게 하면은 SendBuffer에다가 쓰는작업(Write)를 하는 것이고

이렇게 보낸다.

그리고 시작하려면

Start에 이렇게 넣어주도록 하자.

그리고 Server만 시작프로젝트 설정 후 테스트 하면

잘 뜬다.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글