시작하기 앞서....
2편은 Unity3D 와 WinForm 의 통신에 대한 이야기를 할것이며 혹시나마 UForm(Unity3D + WinForm) 에 대해서 잘 모르겠다면 필자가 적은
2015/07/20 - [Programming/Unity3D] - Unity + WinForm 을 구현해보자! 1편 을 보고 이 글을 보도록 하자..
그리고 초보 프로그래머가 적은 내용이므로 틀린 내용, 부족한 설명, 이상한 단어 가 많을 수도 있지만... 이해하고 보시기를 간곡히 부탁드리옵니다.
UFom 의 통신을 구현하기 전 알아보고 가자~!
UForm 에서 쓸수있는 통신방법은 여러가지가 있으나 구글링을 해본 결과 TCP Socket , SendMessage 이 2가지 통신방법이 가장 많이 보였고 이 글에서는 이 2가지를 이용하여 제작하였다. (TCP, SendMessage 관련 내용은 자세한 설명은 생략하고 진행하겠다.)
일단 클라이언트과 서버를 담당할 프로그램을 정해야한다. 필자는 클라이언트을 Unity3D 로 정하고 서버를 WinForm 으로 정했다. 서로 C# 코드를 사용하였기 때문에 이 글을 보고 자신이 원하는 방향으로 바꿔도 좋을꺼 같다.
그럼 본격적으로 본제로 들어가겠다.
UForm 통신 구현하기~! 클라이언트 (Unity3D)
TCP 를 구현하기 전 로딩시간 차이로 인한 터짐현상 (이 문제가 필자한테만 일어나는건지 아니면 다른 코드가 있는지는 잘 모르겠지만.. 필자를 가장 고생시킨 이 문제를 주제로 정하고 글을 진행하겠다.) 을 해결하기 위해 SendMessage 로 클라이언트 (Unity3D) -> 서버 (WinForm) 을 먼저 연결해기로 생각하였다.
Unity3D 가 완전히 로딩이 끝나지 않으면 Socket 에 이상한 값이 들어가며 터져버리므로 Unity3D 가 로딩이 다 끝났다는 것을 WinForm 에 알려주는 형식으로 코드를 구현해야 했고, 필자는 이 부분을 해결하기 위해 UnityWeb 에서 로딩이 끝난 후 가장 먼저 켜지는게 무엇인지 고민하였고 카메라가 켜지면 로딩이 끝났다는 것을 간접적으로 알려주는 것이라는 생각을 하였다.
1 | void OnRenderObject() { } | cs |
http://docs.unity3d.com/450/Documentation/ScriptReference/Camera.OnRenderObject.html : Unity Manual 에서 나오는 설명
이 함수 안에 인제 코루틴을 이용하여 서버스크립트가 들어있는 GameObject 을 실행하도록 하였다. (끄고 키고가 편하도록 GameObject 안에 스크립트를 넣고 제작하였지만 다르게 제작해도 좋다.)
1 2 3 4 5 6 7 8 9 10 11 | void OnRenderObject() { StartCoroutine("StartClient"); Debug.Log("OnRenderObject"); } // http://seonbicode.tistory.com/ IEnumerator StartClient() { text.text = "StartClient On"; // Debug 을 위한 text TCPclient.SetActive(true); // TCPclient 실행 } | cs |
WebPlayer 가 로딩이 끝난 후 카메라에 오브젝트가 렌더링 되면 TCPclient GameObject 가 실행이 되고 TCPclient 라는 GameObject 에 있는 TcpClient 스크립트가 실행된다.
OnRenderObject 는 Update 처럼 켜있는 동안 계속 불러지기 때문에 중간에 체크를 하여 한번만 들어가게 해야한다. 사실 OnRenderObject 를 꼭 안 써도 되지만 확실하게 로딩이 끝났을때 실행되는 메소드이기 때문에 사용한다.
TCPclient 가 실행이 되면 Start 가 가장 먼저 실행이 되며 이 곳에서 ConnectServer(); 함수를 실행한다. Awake() 를 사용해도 괜찬타.
1 2 3 4 | public void Start() { ConnectServer(); } // http://seonbicode.tistory.com/ | cs |
1 2 3 4 5 6 7 8 9 10 11 12 | private void ConnectServer() { /*/////////////////////////////////*/ /* Tcp 서버 구현 SocketAsyncEventArgs */ /*/////////////////////////////////*/ Application.ExternalCall("TcpSet", "프로퍼티값"); /*/////////////////////////////////*/ /* Tcp 서버 구현 ConnectAsync */ /*/////////////////////////////////*/ } // http://seonbicode.tistory.com/ | cs |
(Tcp 클라이언트는 구글링을 하여 직접 적도록 하자. 필자의 소스코드가 너무 미개하여...)
ConnectServer() 에서는 비동기 소켓을 만든 후 Application.ExternalCall("함수명", "프로퍼티값"); 으로 서버 (WinForm) 로 "나 로딩이 끝났고 지금 소켓만들어서 접속하니 서버를 열어라!" 를 시전한다.
Application.ExternalCall("함수명", "프로퍼티값");
- "함수명"에는 서버에서 서버부분이 들어가있는 함수나 그것을 실행시켜주는 함수을 실행시켜주도록 하자. (TcpSet)
- "프로퍼티값" 에는 서버로 보내줄 상태값이나 머 여러가지 정보를 보내는데 사용하자. 사실상 첫 실행을 한 후 Socket 통신을 하게 되면 더 이상 사용할 일이 없다.
- http://docs.unity3d.com/450/Documentation/ScriptReference/Application.ExternalCall.html 자세한 설명은 여기서~
이걸로 클라이언트 (unity3D) 부분은 끝이 났다. 사실상 Unity 는 자신의 상태값만 서버에 보내주고 그 후 여러가지 값을 받아 처리하는 역활만 해준다.
연결 실패 시 몇 초후 재연결 하는 안전장치도 구현하면 좋다.
UForm 통신 구현하기~! 서버 (WinForm)
자아 인제 가장 중요한 서버 부분이다.
지금 UForm 의 현상태는 클라이언트에서 "나 로딩 끝났고 서버 열어서 소켓 받아줘!" 하며 Application.ExternalCall 으로 서버에 통신을 보냈고 클라이언트의 상태값을 받아줄 서버를 구현해야한다.
먼저 Application.ExternalCall 을 받으려면 몇가지 작업을 거쳐야한다.
1 2 3 4 5 | private void Form1_Load(object sender, EventArgs e) { SetUnityClient(); }// http://seonbicode.tistory.com/ | cs |
1 2 3 4 | public void SetUnityClient() // { UnityForm.OnExternalCall += new _DUnityWebPlayerAXEvents_OnExternalCallEventHandler(TcpSet); } // http://seonbicode.tistory.com/ | cs |
먼저 Load 에서 OnExternalcall 을 인스턴스로 생성해주는 코드가 들어가있는 함수를 실행시켜줘야 합니다.
SetUnityClient 을 함수를 살펴보면 UnityForm 라는 것이 있는데, 자신이 선언한 AxUnityWebPlayerAX 의 Name 이다.
속성에서 간단하게 바꾸어 사용하자.
나머지 SetUnityClient 함수에 관련한 내용은 아래 링크에 서술되있습니다. 참고하시기 바랍니다. :
2015/07/10 - [잡다한 자료(번역)/WinForm+Unity3D] - WPF 포함 UnityWebPlayer 문제 해결 및 사용 정보
클라이언트 (unity3D) 가 로딩이 끝난 후 Application.ExternalCall("TcpSet", "프로퍼티값"); 를 하면 TcpSet 함수가 실행이 된다.
1 2 3 4 5 6 | private void TcpSet(object sender, _DUnityWebPlayerAXEvents_OnExternalCallEvent e) { var vClient = e.value; // Unity가 보내준 프로퍼티 값 TCPServer.DoInit(); // 서버 실행 함수 // http://seonbicode.tistory.com/ } | cs |
TcpSet 이 실행되고 TCPServer.DoInit(); 이 실행된다. (여기서 TCPServer 는 필자가 작성한 TcpServer C# 이다.)
1 2 3 4 5 6 7 8 | public void DoInit() { Socket_pThread = new Thread(pStartServer); // Unity policy Socket_Thread = new Thread(ServerSet); //TcpServer Socket_pThread.Start(); // Unity policy Thread Start Socket_Thread.Start(); // TcpServer Thread Start } // http://seonbicode.tistory.com/ | cs |
DoInit() 함수에서 가장 중요한 부분은 pStartServer (Unity policy) 이다.
UnityWebPlayer 는 보안상의 문제로 Unity policy server 를 통하지 않고 통신을 할 수 없도록 하였고, 자세한 설명, 설정 방법은 아래 링크에서 알아보자.
policy server : http://blog.naver.com/loolsasy/20161810693 (loolsasy)님의 블로그
이 후 서버 제작은 여러분의 아름다운 코드로 구현하시기 바랍니다.
서버제작도 다 완료하셨다면 여러분의 눈앞에는 아름다운 구현된 UForm 을 보실 숫 있으실겁니다!!
마치며.....
허접한 내용의 글을 보시느라 수고하셨습니다. 사실 이 방식은 완벽한것은 아닙니다. Unity 와 WinForm 의 로딩차이도 사실 제가 소스를 잘못짜서 버그가 난것일수도 있으니까 말이죠...
그래도 혹시나 구글링하여 이 글을 보시는 여러분들에게 작은 도움이나마 드리고자 이 글을 작성하였습니다. 마지막 3편은 아마 시간이 지난 후 올릴것 같습니다.
제 글을 봐주셔서 감사합니다~!
추가 내용
Visual Studio winForm <---> Unity WebPlayer OCX Works :
http://forum.unity3d.com/threads/visual-studio-winform-unity-webplayer-ocx-works.33685/
Custom Unity3D Launcher [C# Tutorial] (유니티 런쳐 만들기) :
https://www.youtube.com/watch?v=PiTnIc50tAA
(Unity3D [C#]) - Game Launcher Tutorial #1 :
'Programming > Unity3D' 카테고리의 다른 글
How To Draw Line On Screen In Unity (C#) (2) | 2015.09.21 |
---|---|
UForm (Unity3D + WinForm) 에 대한 고찰... (0) | 2015.07.27 |
AssetBundle 관하여... #1 (0) | 2015.07.23 |
UForm 을 제작하기 전 준비하기 (2) | 2015.07.20 |
Unity + WinForm 을 구현해보자! 1편 (1) | 2015.07.20 |
최근댓글