Unity uses Websocket to implement WebGL online games (no plug-ins) and websocketwebgl

Source: Internet
Author: User
Unity uses Websocket to implement WebGL online games (no plugins), websocketwebgl
Opening

Before Unity supports WebGL, if you want to do page games, you need to convert to Flash platform release, but it is very troublesome and there will be a lot of things that need special handling. Or if you don't use Flash, you need Unity's WebPlayer, which is a web plug-in. Before running, you must install this plug-in on your browser before you can run Unity programs.
BUT !!! Now Unity can be directly translated into JS and rendered using WebGL on the browser, haha, nice. Solved the problem of page game plugin. But what about networking? The traditional Socket method is definitely not working, the browser will not let you use Socket for transmission. However, another new feature of HTML5 is Websocket, which can establish a socket long connection on the browser. How to achieve it? I tried a lot of ways, and finally found a really feasible way, and it seems that this is the only way, so I share it ~~~
  practice
 
!! !! !! DEMO full source code: http://www.cnblogs.com/yinlong1991/p/5090289.html! !! !!
Let me describe the approximate logic first:
Unity can call Web JS, and then JS uses WebSocket to connect to the server. Websocket sends the recovered message packet to Unity through SendMessage. code show as below:


    / * ---------------- WebGl Platform --------------------- * /
    [DllImport ("__ Internal")]
    private static extern void ConnectJS (string str);
    [DllImport ("__ Internal")]
    private static extern void SendMsgJS (byte [] data, int length);
    [DllImport ("__ Internal")]
    private static extern void CloseJS ();
    [DllImport ("__ Internal")]
    private static extern void AlertJS (string str);
 
    private void Connect_2 (string str)
    {
        ConnectJS (str);
    }
 
    private void SendMsg_2 (MessageBase msg)
    {
        byte [] data = SerializeMsg (msg);
        SendMsgJS (data, data.Length);
    }
 
    private void Close_2 ()
    {
        CloseJS ();
    }
 
    private void OnOpen_2 ()
    {
        OnOpen ();
    }
 
    private void OnMessage_2 (string msg)
    {
        string [] byteIntS = msg.Split ('');
        byte [] data = new byte [byteIntS.Length];
        for (int i = 0; i <byteIntS.Length; i ++)
        {
            data [i] = (byte) int.Parse (byteIntS [i]);
        }
        OnMessage (data);
    }
 
    private void OnClose_2 ()
    {
        OnClose ();
    }
    / * --------------------- Serialze ------------------------ * /
    BinaryFormatter binFormat = new BinaryFormatter (); // Create a binary serializer
    private byte [] SerializeMsg (MessageBase msg)
    {
        MemoryStream stream = new MemoryStream ();
        binFormat.Serialize (stream, msg);
        return stream.GetBuffer ();
    }


 The jslib used on the web side. This file needs to be placed in the Plugins directory and will be translated into JS code and run on the browser. My path is: Assets \ Plugins \ WebGL \ WebsocketJS.jslib






var WebsocketJS =
{
$ webSocket: {},
ConnectJS: function (url)
{
var s_url = Pointer_stringify (url);
webSocket = new WebSocket (s_url);
webSocket.onmessage = function (e)
{
if (e.data instanceof Blob)
{
var reader = new FileReader ();
reader.addEventListener ("loadend", function ()
{
var array = new Uint8Array (reader.result);
var msg = "";
for (var i = 0; i <array.length; i ++)
{
if (i == array.length-1)
msg + = array [i];
else
msg + = array [i] + "";
}
SendMessage ("WebSocket", "OnMessage_2", msg);
});
reader.readAsArrayBuffer (e.data);
}
else
{
alert ("msg not a blob instance");
}
};
webSocket.onopen = function (e)
{
SendMessage ("WebSocket", "OnOpen_2");
};
webSocket.onclose = function (e)
{
SendMessage ("WebSocket", "OnClose_2");
};
},

SendMsgJS: function (msg, length)
{
webSocket.send (HEAPU8.buffer.slice (msg, msg + length));
},
Ranch
CloseJS: function ()
{
webSocket.close ();
},
Ranch
AlertJS: function (msg)
{
var s_msg = Pointer_stringify (msg);
alert (s_msg);
}
};

autoAddDeps (WebsocketJS, '$ webSocket');
mergeInto (LibraryManager.library, WebsocketJS);


 Note that the format of jslib is quite special. $ WebSocket: {}, means to declare a global variable, autoAddDeps (WebsocketJS, '$ webSocket'); Is this variable used? Anyway, I want to add in.




All the functions in it are called by Unity, such as the above C # code: private static extern void ConnectJS (string str); In this way, you can call the JS method.
detail:
    var s_url = Pointer_stringify (url); All the contents of str type should be converted using Pointer_stringify function.
    HEAPU8.buffer.slice (msg, msg + length) All byte [] types of data need to be converted using the HEAPU8.buffer.slice (byte [] data, int length) function.
    There are some other data type conversions, which are not used for no detailed explanation for the time being. You can also refer to the code of others: https://github.com/hecomi/UWO/blob/master/Assets/Plugins/WebSocket.jslib Is the most popular piece of jslib code for foreign websites, but I feel bad! !! !!
The point is to say the content of the webSocket.onmessage method body


if (e.data instanceof Blob)
{
var reader = new FileReader ();
reader.addEventListener ("loadend", function ()
{
var array = new Uint8Array (reader.result);
var msg = "";
for (var i = 0; i <array.length; i ++)
{
if (i == array.length-1)
msg + = array [i];
else
msg + = array [i] + "";
}
SendMessage ("WebSocket", "OnMessage_2", msg);
});
reader.readAsArrayBuffer (e.data);
}


 It can be seen from the code that the received data is a Blob block type, then read the byte stream through FileReader, and then convert the byte stream into an 8-bit unsigned integer array Uint8Array and then put it into the string with spaces, why Want to write like this? Doesn't this greatly increase the amount of data transmission (PS: non-network traffic transmission, just between JS and Unity). The reason is that I have to send the data string to Unity through the SendMessage ("WebSocket", "OnMessage_2", msg); function. I checked a large amount of documentation. This product does not support the transmission of all other data types except string. Text type characters cannot be transmitted. For example, the '\ 0' character fails to be transmitted. I wipe, then I can only use the brute force method described above to encapsulate String type strings, and then go to Unity to do parsing. This is why I said above that the kind of jslib used on foreign websites is not good for reading network packets.



Transmission methods on foreign websites:
C # code:


[DllImport ("__ Internal")]
private static extern void SocketRecv (int socketInstance, IntPtr ptr, int length);
[DllImport ("__ Internal")]
private static extern int SocketRecvLength (int socketInstance);
 
public byte [] Recv ()
{
int length = SocketRecvLength (m_NativeRef);
if (length == 0)
return null;
byte [] buffer = new byte [length];
IntPtr unmanagedPointer = Marshal.AllocHGlobal (length);
SocketRecv
(m_NativeRef, unmanagedPointer, length);
Marshal.Copy (unmanagedPointer, buffer, 0, length);
Marshal.FreeHGlobal (unmanagedPointer);
return buffer;
}


 jslib code:






SocketSend: function (socketInstance, ptr, length)
{
var ptr = HEAPU32 [ptr >> 2];
var socket = webSocketInstances [socketInstance];
socket.socket.send (HEAPU8.buffer.slice (ptr, ptr + length));
},
 
SocketRecvLength: function (socketInstance)
{
var socket = webSocketInstances [socketInstance];
if (socket.messages.length == 0)
return 0;
return socket.messages [0] .length;
},


 I only talk about his general operating mechanism. Unity calls JS to connect to the server. After the server returns the package, JS caches it first. Then Unity calls JS in a circular manner to read the header pointer of the received data, and then reads the data block data according to the length. . This loop method undoubtedly increases the delay of the datagram, and it is also very inconvenient to use!




Note: My method also needs to buffer the package data in C #. The SendMessage function callback is in another thread. You cannot change the value of the main thread Transform and other components.
The server does not restrict the language, as long as it is in compliance with the Websocket specification, it can accept and send data. C # see: https://github.com/sta/websocket-sharp
!! !! !! DEMO full source code: http://www.cnblogs.com/yinlong1991/p/5090289.html! !! !!
  Concluding remarks
 
Anything you don't understand, just ask me.
Finally, I wish you all a Happy New Year, 2016 to find the female friends
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.