Page 1 of 1

Unity Fighting Game with 2 players

Posted: 17 Feb 2017, 14:50
by Aymeric
Hi there,

So I read a lot of documentation and go through the tutorials. I'm working on a fighting 2D game (like Street Fighter) with 2 players only made with Unity. Unfortunately I didn't find enough informations about this, the topics on the forum were very brief.

I'm using SmartFoxServer for Room creation (2 players max) and then the fighting part though it could be done via P2P or Socket (but I don't want to bother with Firewall issue etc.).

I want to benefit from Unity engine and its physics, so the Room creator will be the Master and the other one the Slave. Since there are only 2 players, I don't need to run the physics on the server, right? It will save me lot of time because it will be easier with Unity.

This is my current process:
- the Master client run physics on its side, and send users positions to the Server.
- the Server dispatches this information to the other player.
- the Slave receives both user positions and make an interpolation.
- the Slave sends its input to the server.
- the Server dispatches the input to the Master.
- The Master applies input on the remote player and so moves its physics. Then the current process starts again.

Obviously I sent only informations when something is changing, so if a player doesn't move there isn't any message sent to the Server.

As you can imagine, I suffer from lag... What I think to do next :
- use UDP.
- use RoomExtension instead of ZoneExtension, does it will change anything concerning performances?
- I send messages in a Unity's update method (so 60 fps), move to a 10 fps max method.
- put physics too on Slave side so it can also move on its side directly after the input and then interpolate from the Master's result.

What do you think? Am I missing something? With my architecture, the slave must send informations to server then master then go back to server then slave, is it a big mistake or not? If it's, I will have to change all my fighting game logic on the server and it will take way more time to program.

Thanks for your help,
Aymeric

Re: Unity Fighting Game with 2 players

Posted: 17 Feb 2017, 15:27
by Lapo
Hi,
yes this will work. Running physics on the client makes sense. From a security standpoint there's always a risk that somebody will hack the client and use such modded app to put the other player at a disadvantage. This however is an issue basically with any Unity multiplayer game, since they are all P2P, basically. There are ways to defend against this, but let's not go off topic.

- use UDP.

For some messages yes, such as position changes, but not for everything, since UDP messages can get lost. TCP on the other hand attempts retransmissions so packets will get there, eventually.

- use RoomExtension instead of ZoneExtension, does it will change anything concerning performances?

No, not really.

- I send messages in a Unity's update method (so 60 fps), move to a 10 fps max method.

This is more of a problem. If you send packets at 60hz you will leave out a lot of people without a blazing fast connection. It would be best to optimize the game for 20-30pps (packets per second) for TCP and with UDP you can experiment with pushing it a bit higher.

put physics too on Slave side so it can also move on its side directly after the input and then interpolate from the Master's result.

This is more an area of experimentation. It certainly makes sense as it will help alleviate input lag for the slave. Maybe only the slave will be able to register a hit, though.

Cheers

Re: Unity Fighting Game with 2 players

Posted: 20 Feb 2017, 15:26
by Aymeric
Thanks for the detailed answer Lapo. So I moved to UDP for transform update, and reduce packets frequency that way (in my Update loop);

Code: Select all

if (masterTimeLastSending >= SmartFoxConnection.sendingPeriod) {

   SmartFoxGame.Instance.SendLocalPlayerPhysicsPosition();
   localPlayer.transform.hasChanged = false;

   masterTimeLastSending = 0;
   return;
}
masterTimeLastSending += Time.deltaTime;


My ping has reduced, this is a really good thing. But the synch is far to be good. For the interpolation, I'm trying to use the NetworkTransformInterpolation class from the FPS example. So my Master sent its date with the position, at the opposite of the samples (where it comes from the Java Server).

Re: Unity Fighting Game with 2 players

Posted: 23 Feb 2017, 18:55
by Aymeric
Hi,

Concerning the previous code:

Code: Select all

SmartFoxConnection.sendingPeriod = 0.1f;

So it's just 10 ten time by second, it should be good enough, right?

I used the NetworkTransformInterpolation script http://pastebin.com/raFyYzi9 from the FPS demo. Unfortunately, it isn't smooth enough : I've some jerk and teleportation.

Since the Date isn't generated by the Server, but the Master, I create it that way with C#:

Code: Select all

trans.TimeStamp = (DateTime.UtcNow - new DateTime (1970, 1, 1)).TotalMilliseconds;


On the server side, all my handlers use @Instantiation(InstantiationMode.SINGLE_INSTANCE), it shouldn't be a bad thing for sending transfrom update right?

Also my server's methods are really basic:

Code: Select all

public void handleClientRequest(User user, ISFSObject params) {

   params.putInt("id", user.getPlayerId());
   Room room = user.getLastJoinedRoom();
   
   send(CMD_UpdateRemotePlayerPhysicsPos, params, room.getUserList(), true);
}


I would be really suprised if the code in the FPS demo isn't running fine, but on my side I don't know what to check next.

Any ideas?

Re: Unity Fighting Game with 2 players

Posted: 24 Feb 2017, 09:27
by Lapo
Aymeric wrote:Hi,
So it's just 10 ten time by second, it should be good enough, right?

Yes, although it needs to be fine tuned to your needs. If you feel it's fine, then I suppose it is :)

I used the NetworkTransformInterpolation script http://pastebin.com/raFyYzi9 from the FPS demo. Unfortunately, it isn't smooth enough : I've some jerk and teleportation.

Since the Date isn't generated by the Server, but the Master, I create it that way with C#:

Code: Select all

trans.TimeStamp = (DateTime.UtcNow - new DateTime (1970, 1, 1)).TotalMilliseconds;


On the server side, all my handlers use @Instantiation(InstantiationMode.SINGLE_INSTANCE), it shouldn't be a bad thing for sending transfrom update right?

Right, no problem there.

Also my server's methods are really basic:

Code: Select all

public void handleClientRequest(User user, ISFSObject params) {

   params.putInt("id", user.getPlayerId());
   Room room = user.getLastJoinedRoom();
   
   send(CMD_UpdateRemotePlayerPhysicsPos, params, room.getUserList(), true);
}


I would be really suprised if the code in the FPS demo isn't running fine, but on my side I don't know what to check next.

Any ideas?

Checking for what? For the jerkiness you mentioned?

There's a fine tuning process that needs to be done in order to strike a balance between the amount of data sent and final result on screen. If you push the send rate to 50-60/sec and test locally you should have no jerks/jumps at all.

Of course you can't force online players to keep that pace as many don't have a super low latency connection. The trick is to find an appropriate packet rate and compensate the missing data (e.g. temporary slow downs etc...) with animation and smoothing. These are just client side "tricks" that allow you reduce those artifacts on screen and give the illusion that everything is smooth.

How to do this in your specific case it's difficult for me to say and I think you will have to experiment a bit. Typically it all boils down to filling the gaps with animations, so that there are little to no jumps.

Classic examples are: if you're missing a bunch of updates from the other player keep it moving in the most recent direction. When you finally get a new update don't move it abruptly but instead try using a smooth animation, if possible. Etc...