Unity

[Unity] WebGl환경 iis로 Websocket 통신 방법 Javascript NativePlugin

usingsystem 2023. 4. 3. 17:05
728x90

https://docs.unity3d.com/kr/2021.1/Manual/webgl-server-configuration-code-samples.html

 

WebGL: 서버 설정 코드 샘플 - Unity 매뉴얼

아래 코드 샘플은 WebGL로 작업할 때 서버를 설정하는 방법을 보여줍니다. 다음 샘플은 IIS 및 Apache 서버에 적용됩니다. WebGL 서버 설정에 대한 자세한 내용은 WebGL: 압축 빌드 및 서버 설정을 참조

docs.unity3d.com

https://docs.unity3d.com/kr/2018.4/Manual/webgl-deploying.html

 

WebGL: 압축된 빌드 배포 - Unity 매뉴얼

릴리스 모드에서 WebGL 프로젝트를 빌드하는 경우(빌드 퍼블리시 참조), Unity는 빌드의 다운로드 크기를 줄이기 위해서 빌드 결과 파일을 압축합니다. 여기서 사용되는 압축 타입은 퍼블리싱 설정

docs.unity3d.com

 

WebGl 환경에서 Unity Websocket을 하면서 많은 어려움을 느꼈으며 알아본 내용을 적으려고 한다.

 소켓 통신을 하고 있는 클라이언트를 갑자기 Web에 올려야 하는 상황이 생겼다. 결국 서버는 소켓 통신도 해야 하며 웹소캣통신을 해야 됐고 클라이언트도 web 버전과 windows 용 두 가지를 Unity 전처리를 통해 나눠주며 만들어야 했다.
소켓 통신을 주로 하던 나에겐 Websocket에 대해 무지했으며 WebGl의 특성 또한 몰랐기 때문에 Websocket에 대해 공부

해서 socket과 websocket을 둘 다 포함하는 서버와 클라이언트를 만들었다. 테스트를 unity Editor에서 진행하였으며 만족하는 결과가 나왔다. 하지만 WebGl로 빌드 한순간부터 문제가 생기기 생겼다. 빌드를 하여 나온 html을 실행하니 실행부터 오류가 발생하여 문제가 생겼고 실행을 하고 나서는 프로그램에서 통신이 안 되는 큰 문제가 생겼다 ㅠㅠ 많은 구글링을 하였고 해결했던 내용을 써보려고 한다.

.Net을 상속받는 모든 네트워크는 WebGl 환경에서 동작하지 않는다.(https://docs.unity3d.com/kr/2017.4/Manual/webgl-networking.html)

목차

  • WebGl 빌드 후 실행 방법 (IIS 사용)
  • . Net을 상속받아 WebSocket클라이언트를 만 들 경 우
  • WebSocketSharp 확장형 사용방법
  • WebSocketDemo 활용 팁

WebGl 빌드 후 실행 방법 (IIS 사용)

1.Setting Decompression FallBack을 체크

2. 빌드

3. 빌드 후 생성되는 폴더이며 index.html을 클릭하여 실행하면 아래와 같이 빨간색으로 오류가 표시된다.

빌드된 파일을 웹서버에 올리지 않고 실행해서 발생하는 문제라고 한다. 결국 여러 서버가 있겠지만 IIS서버에 올려보려고 한다.

 

 

4. IIS 설치 IIS설치를 위한 글이 아니기 때문에 자세한 내용은 찾아보길 바랍니다.

5. IIS에 Build파일 등록

1. 웹사이트 추가 누르기

1. 사이트 이름을 원하는 이름으로 기입

2.WebGl로 빌드한 경로 선택

3. 원하는 포트 입력 후 확인

6. MIME 형식 등록

중요한 부분이다 MIME를 클릭하여 

. unityweb

application/octet-stream

를 추가해줘야 한다.

1. 추가클릭

2. 입력

. unityweb

application/octet-stream 입력 후 확인

추가하면 Build파일에 web.config가 생성됨을 확인할 수 있다.

7. 빌드파일 실행 방법

웹 사이트 찾아보기를 클릭하면 빌드파일이 실행된다.


. Net을 상속받아 WebSocket클라이언트를 만 들 경 우 

. net을 상속받아 TcpListener이나 socket을 사용하여 websocket을 만든 후 unity Editor에서 테스트를 진행하면 잘될 것이다. 하지만 WebGl로 빌드를 하고 위와 같이 서버에 올려서 실행시키면 켜지기만 할 뿐 결국 JavaScripts에러가 출력된다.

. Net을 상속받는 모든 네트워크는 WebGl 환경에서 동작하지 않는다.(https://docs.unity3d.com/kr/2017.4/Manual/webgl-networking.html)

 

wwwUnityWebRequest를 사용한다면 서버에서 먼저 클라이언트에게 정보를 줄 수 없기 때문에 웹소캣이라고 할 수 없다. 결국 해답은 javascript를 native plugin 하여 c#에서 사용해야 한다는 뜻이다. 대표적으로 c#의에서 websocket을 사용하기 편리한 라이브러리인 WebSocketSharp 사용하면 편리하지만 이것만을 사용해서는 켜지기만 할 뿐 동일한 javascripts 에러가 출력될 것이다. 결국 websocketsharp에 javascript를 연동한 확장형을 사용해야 한다. 

 

WebSocket Library 및 예제

 

WebSocketSharp는 정말 강력하고 편리한 라이브러리는 맞지만 그래도 한번 직접 만들어 보는 것 을 추천한다.

 

1.

WebSocketSharp 예제 및 dll 

https://github.com/sta/websocket-sharp

 

2.

javascript확장형  WebSocketSharp예제 안에 dll이 미포함 이기 때문에 dll은 위에서 받아서 넣거나 Nuget에서 받아야 한다.

https://github.com/jirihybek/unity-websocket-webgl

 

3.

WebSocketSharp가 아닌 다른 방법

https://github.com/psygames/UnityWebSocket

 

dll은 Nuget에서도 다운로드할 수 있다. 

.Net FrameWork
.netCore


WebSocketSharp 확장형 사용방법

1. 예제 다운

https://github.com/jirihybek/unity-websocket-webgl에서 예제를 다운로드한다.

다운 받은 예제

2. Unity 폴더 구성

Assets안에 Libs, Plugins, Scripts 폴더를 추가한다.

Unity Forder

 

Libs에 websocketsharp dll을 넣는다.
plugins에 Websocket jslib를 넣는다. !!핵심!!
제공 소스를 넣는다.

3. 오브젝트와 연결

오브젝트 컴포넌트에 demo cs를 연결한다.

demo에 url을 수정하여 사용한다.

 

4. 실행 시 발생 Runtime 오류

javaScripts 에러 메세지

해당 오류는 우리가 다운로드하여서 넣은 Plugins폴더에 Websocket.jslib에서 발생하는 문제로 Unity 2021.2에서는 Runtime 변수가 존재하지 않으며 Module ['dynCall_*']로 대체해서 사용해야 한다.

즉 webSocket.jslib에서 Module ['dynCall_*1'](*2, *3, *4)에 대한 모든 Runtime.dynCall('*1', *2, [*3, *4]) 변경해야 한다.

 

Websocket.jslib에서 instance.ws.onmessage 함수 안에

Runtime.dynCall("viii", webSocketState.onMessage, [ instanceId, buffer, dataBuffer.length ]);

부분을 Module ['dynCall_viii']( webSocketState.onMessage, [ instanceId, buffer, dataBuffer.length ]); 로 수정해 주고 다시 빌드하면 문제가 해결된다.


WebSocketDemo 활용 팁

        ws.OnMessage += (byte[] msg) =>
        {
            TextMeshProUGUI txtTest = GameObject.Find("TestText").GetOrAddComponent<TextMeshProUGUI>();
            Debug.Log("WS received message: " + Encoding.UTF8.GetString(msg));
        };

WebSocketDemo에 onMessage이벤트는 서버에서 주는 데이터를 받는 부분이다. 여기서 맞바로 Unity의 오브젝트를 참조하여 변화시키려고 한다면 Unity버전에 따라 다르겠지만 21 버전에서는 오류는 발생하지 않지만 오브젝트의 참조가 적용되지 않는다. 그 이유는 Unity오브젝트를 참조하기 위해서는 무조건 Unity Thread에서 참조해야 하기 때문이다.

 

즉 OnMessge를 호출하는 Thread는 Unity Thread가 아니기 때문에 Unity 오브젝트를 참조할 수 없다.

 

결국 JobQueue와 같은 방식으로 어떤 행위나 결과를 담고 해당 부분을 Unity  Thread에서 실행시키면 된다.

 

아래와 같이 Queue에 결괏값을 담아 실행하는 코드를 참고하기 바랍니다. 사실 디테일하게 Action을 담는 방법이 좋다고 생각한다.

 

    Queue<string> wsQueue = new Queue<string>();
    
	ws.OnMessage += (byte[] msg) =>
        {
            wsQueue.Enqueue(Encoding.UTF8.GetString(msg));
            Debug.Log("WS received message: " + Encoding.UTF8.GetString(msg));
        };
    void Update () {

        if (wsQueue.Count > 0)
        {
            string str = wsQueue.Dequeue();
           txt.text = str;
            txtbtn.text = str;
        }
	}

OnMessage에서 결과값을 단순히 Queue에 Push 한 후 Update인 Unity Thread에서 호출하여 행위를 일으키면 된다.

 

Update함수는 Unity Thread에서 호출하기 때문에 안전하게 오브젝트를 참조하여 값을 변경할 수 있다.

728x90