Unity Plug-in using Berkeley Sockets
- bigmekben
- Jul 12, 2022
- 3 min read
Today I completed a Unity demo project. Here were my goals for the project:
Make a "useful" Unity plug-in using native C++ code.
Practical experience with Berkely Sockets.
Get a working demo to prove that a game could be made with the plug-in (even though I won't use this for an actual game).
Here is a video of the demo working on one of my lab PCs:
To test the demo, I have a copy of the Unity build running on my laptop and my tower PC.
Here is what I put into this to make it work:
I built a DLL in C++ named BerkleySocketCPPPlugin.dll (I neglected to double-check the spelling of Berkeley)
I build a set of C# scripts on the Unity side which import the plugin functionality, e.g.:
[DllImport("BerkleySocketCPPPlugin")] static extern int LatestXFromRemote();
[DllImport("BerkleySocketCPPPlugin")] static extern int LatestYFromRemote();
[DllImport("BerkleySocketCPPPlugin")] static extern void SendXToRemote(int value);
[DllImport("BerkleySocketCPPPlugin")] static extern void SendYToRemote(int value);
The LocalPlayer Unity script reads player input from the local keyboard. It also sends x and y coordinates to the remote host via the plugin functions.
The RemotePlayer Unity script reads x and y coordinates from the plugin functions.
The Multiplayer Game Programming book had helper/wrapper classes. However, I ended up needing to write my own code from scratch and abandoning the wrapper classes.
Here is where I learned the parts that I had to put together to build this project:
Berkeley Sockets: used the digital book "Multiplayer Game Programming" by Joshua Glazer and Sanjay Madhav
Unity plug-ins: read the Unity online reference pages
Besides the obvious of learning how to write and use a Unity plugin, I learned the following as part of this exercise:
Using NetMon to prove that the traffic was leaving one lab PC and arriving at the other. This was necessary because my code didn't seem to be receiving anything from the other PC at first.
The fact that just because I spawn a CoRoutine from Unity script, does not mean that the invoked code will run on another thread! My first attempt, I naïvely thought I could block while reading from the network in a tight loop on a second thread directly from Unity. Instead, Unity would stall until the read received data.
Some frustrations I ran into:
It was disappointing that I couldn't block on read on a separate thread. Instead, I used non-blocking I/O mode. Arbitrarily, I do 5 reads with 20 milliseconds between each, each frame of the RemoteHost script's Update.
At first, the networking was only working one way. I found out that this is because I was running directly from Unity on the laptop. Once I started running from the .exe build on the laptop, it worked in both directions! I expect some shenanigans with ports on the Unity editor side.
(I understand that a lot more than this goes into making workable, playable networking game code. But at least this illustrates the fundamentals.)
Now that I proved that this works, I will probably shelve it, and instead look into Unity's latest offering for a networking solution before making an actual networked game. I might return some day to implement other subjects from the Glazer/Madhav book such as replication, just for the practice.
This isn't the first time I've made a demo like this. About 16 years ago, I used Java (and a Java Networking book by O'Reilly press) to make a similar demo. I didn't have Unity back then, and I don't remember what I used for the graphics layer, but I used simple filled red/blue circles to track mouse movement on the local and remote hosts. I used my college PC and my parents' family PC for the experiment.
Thanks for reading!
~Ben


Comments