I’ve worked on numerous projects with Unity3D which involve my own networking solution ( Stand alone server, written without the use of Unity, usually in Java or C# ) While the way you handle networking on the Unity Client is the same, how you have to go about calling Unity related functions has been more than annoying.
Around two years ago I was doing research and it seemed like the renowned method to solve this problem was to call a function that sets some variables, then check those variables in the Update() function and do something with them, and example of what this looks like is below:
private bool UpdateRequested = false;
// This would be called from the network thread
public void ApplyUpdateRequest() {
UpdateRequested = true;
}
// This would be called from the Unity thread (from update())
private void HandleUpdateRequest() {
// Do Unity Related code, such as GameObject.GetComponent<Script>
UpdateRequested = false;
}
void Update() {
if(UpdateRequested) {
HandleUpdateRequest();
}
}
As you can see, this can quickly cause a ridiculous amount of clutter (Example from a tutorial video I wrote):
Code
ApplyCharacterLocationUpdate(int, Vector3, Vector3) is what’s called from the network thread
UpdateCharacterLocationUpdate() is called from Update() when ApplyCharacterLocationUpdateRequired is true
bool ApplyCharacterLocationUpdateRequired = false;
int ApplyCharacterLocationUpdateID;
Vector3 ApplyCharacterLocationUpdatePosition;
Quaternion ApplyCharacterLocationUpdateRotation;
public void ApplyCharacterLocationUpdate(int networkID, Vector3 position, Quaternion rotation)
{
ApplyCharacterLocationUpdateID = networkID;
ApplyCharacterLocationUpdatePosition = position;
ApplyCharacterLocationUpdateRotation = rotation;
ApplyCharacterLocationUpdateRequired = true;
}
void UpdateCharacterLocationUpdate()
{
NPlayer updatedPlayer = MasterClient.GetPlayerForID(ApplyCharacterLocationUpdateID);
updatedPlayer.gameObject.transform.position = ApplyCharacterLocationUpdatePosition;
updatedPlayer.gameObject.transform.rotation = ApplyCharacterLocationUpdateRotation;
ApplyCharacterLocationUpdateRequired = false;
}
As you can see, this is an absolute… clusterfuck. This doesn’t even include the lines of code that read the data from the packet sent from the server.
The more I think about it and realize solutions like SmartFoxServer and Photon can call Unity3D functions with ease, there’s only two immediate answers.
1: They run on the same thread, without blocking it in any way.
2: There’s something I’m missing which allows Unity to function properly while multithreading.
Either way, both of the solutions I can come up with for the issue, I can’t come up with a way to implement them. I use TcpClient on the C# side for my network client, which by default is a Blocking-IO client. There’s ways to make the TcpClient Asynchronous (NIO) but I don’t have any experience with it and the information I’ve found online is fairly limited. I don’t really like C#… But, You gotta use what you gotta use.