Network Jitter - I'm Desparate?
Hey all,
I have everything working great, almost done the alpha build of my game, but this network jitter is preventing me from releasing anything. I've scouered the boards, but haven't found the resolution and I know its gotta work. I'm using NetworkRigidBody and Unity4, I have Observed set to NetworkRigidBody, with it enabled on both the sending and receiving sides. I've taken time to diagnose the code and I understand it and I'm pretty confident the code looks valid. If my client isn't moving and the remote avatar is moving I notice the jitter, but if we're both traveling in the same direction at the same speed, and I'm very close to the other player, I see the other player jitter very bad. The faster I go the worse I see it. Is there another version of NetworkRigidBody that works better? Might it be an issue with prediction? I'm traveling perfectly straight, no turning, so even prediction should be pretty simple. I even commented out the prediction code thinking it was moving too far forward, then it had to back up and reset, but I still had the jitter. This is a show stopper and I'm not ready to give up. Anyone have any magic for me.... PLEASE!!!!
I'm waiting on a new network capture card, should be here any day. Then I'll upload a video if its not resolved by then.
I have everything working great, almost done the alpha build of my game, but this network jitter is preventing me from releasing anything. I've scouered the boards, but haven't found the resolution and I know its gotta work. I'm using NetworkRigidBody and Unity4, I have Observed set to NetworkRigidBody, with it enabled on both the sending and receiving sides. I've taken time to diagnose the code and I understand it and I'm pretty confident the code looks valid. If my client isn't moving and the remote avatar is moving I notice the jitter, but if we're both traveling in the same direction at the same speed, and I'm very close to the other player, I see the other player jitter very bad. The faster I go the worse I see it. Is there another version of NetworkRigidBody that works better? Might it be an issue with prediction? I'm traveling perfectly straight, no turning, so even prediction should be pretty simple. I even commented out the prediction code thinking it was moving too far forward, then it had to back up and reset, but I still had the jitter. This is a show stopper and I'm not ready to give up. Anyone have any magic for me.... PLEASE!!!!
I'm waiting on a new network capture card, should be here any day. Then I'll upload a video if its not resolved by then.
0
Comments
Try my code (150ms interpolation, with still PUNs default 100ms OnSerialize)
However, I did get some code from Duhprey off the unity forums with a modified piece of code from this http://wiki.unity3d.com/index.php?title ... ition_Sync, but Duhprey's version further added control inputs to help with the prediction and its working well. I'm still working through some tweaks and refinements, but when I'm done, with Duhprey's permission I'll post it.
What is your PING to the cloud servers? Are you using the closest region?
Otherwise I'll wait on your results.
I had several different variations of the original NetworkRigidBody but none worked as advertised. I don't know what I'm doing different. I've tested on both my own server and the Photon cloud server with the exact same results. It's not a ping issue. Avg ping is around 2-3ms because I'm actually over wifi, but its still fine. I finally received a variation of the code from Duhprey on the Unity forums and his code worked great for me. Furthermore, he also passes player control input to help stream line the smoothing based on inputs and also helps the prediction. It's actually pretty cool. I've included the final variation below.
I have tested all these solutions including the original 'ThirdPersonNetwork.cs' which is delivered with the 'DemoWorker' example. The jitter is always there... sometimes its interpolated. But I get never a really smooth movement. I like to use Photon in my 'neXt - CGM rc Heli Simulator'.
I think, the initial problem must be fixed. The send rate must match the frame rate or (sometimes better) the half of the frame rate.
I've changed them in 'PhotonNetwork.cs':
private static int sendInterval = 16;
private static int sendIntervalOnSerialize = 16;
Is the failure on my site? 1000 / 16 = 62.5 times per second ?
All the best,
Klaus
We usually check the send queue when OnSerialize was called, so there is less delay due to that. Setting the sendInterval to 16 might not be needed.
What you attempt is the brute-force approach of networking.
Even if you send every frame, the delay and potential variance in delivery of the messages won't go away. If the pure network roundtrip takes ~100ms, all actions are still delayed this much on the remote machines, no matter how many updates you write. Worse: Some updates might only take 80ms and some 120ms. If you don't smooth this (or fix this inconsistency otherwise), you still end up with non-linear updates from the other machines.
If you are this sensitive to timing and updates, you can't assume they will happen consistently every frame (or second frame).
You need to analyze how you can better anticipate movements of remote clients. Maybe send additional info like velocity and direction. Depending on the game, it might also be easier to send input and replicate the reactions to that, instead of sending the current state in high frequency (cause the amount of input it more or less constant, while an update/frame is more than an update every 10 frames).
You cant send every frame, network technology is no where close to being able to keep up. Multiply that by each player and its even worse. You need to rely on smoothing and prediction for best results. The last example I posted above works perfectly for me so I'd double check your implementation. I have both human and AI all being syncd this way with no more jitter.
versionPUN = "1.22.1"
http://www.youtube.com/watch?v=2baEiS93WMU&feature=youtu.be
The sync problem is every second. I see that also in the 'Worker Demo' example.
My computers are connected to a high speed cable network and I can play other network games in the same configuration without any problems.
What's going wrong? Do you have any ideas?
Are you running the unmodified samples?
You could try to update PUN but I doubt there have been changes that fix anything that could cause it.
If you got Unity Pro you could try and run the profiler, too.
I'm not seeing the jitter in your example, at least not the kind of jitter I originally experienced. For me the jitter actually caused the object to move in a way that resembled moving forward+3, backward-1, forward+3, backward-1
You look like you're continually moving forward, but its just not smooth. Try the lerp first, then worry about prediction later.
@Quadgmin: That's not mine... it's an example project which I have downloaded from Unity3D asset store. It's name is 'Photon Unity Networking Free', version 1.22.3, September 06, 2013. This demo is running with 60 fps. You see the naked problem in the upper line (Transformation Sync). And I think it's doesn't make any sense to interpolate that. In the other lines, the problem is interpolated, but still there. It's far away from a perfect movement.
Now I have double checked everything:
- deleted all old files of the PUN demo
- downloaded it again from Unity 3D AssetStore and imported it into an empty project
- I've added my AppID in the PUN Wizard window, selected the region 'EU' and saved it
- then I built the App and started it on a second computer
When I start the App and select there 'Synchronization Demo' I still get the same result :-(
I use the 20 CCU Photon Demo Account. When I log in and take a look at the settings on your webpage, I see this: 'This app is on the free plan. We recommend you upgrade before using it in production.'
I don't like to purchase server power while I don't know if this is working as expected?
@Tobias: I'm on Unity Pro v4.2.1f4 (OSX and Windows), I don't see a problem in the Profiler. Is there anything I have forgotten? Any setup changes in the PUN files?
I have also checked again all the other hardware I used by testing a network game to make sure it's not my computers, router, service provider, ...
Of course, when that is running, I'll purchase server power from Photon before I release the next update of my App which brings online meetings.
I haven't played with the Photon Sync demo. When I get some time I'll try and load it and have a look. Are you using all the sample code from the demo? PUN uses an override for the Observed property, just like Unity does. The override points to a user defined class that in my code sample above is called NetworkRigidBody, but can be called anything. Are you using the overridden code, or that native code in the demo? To use this code you must either replace the native demo code, or update the project to change the observed to use this new class/component.
In my simulator, I've tested your NetworkRigidBody script (without input controls because that doesn't make sense in a simulation). Your script interpolates way better than the methods in the Photon samples. But the jitter which occurres every second is still visible.
So I changed the lerp code just a little. try this and let me know if it's a little better. It's just smoothing, no prediction so you'll have to add that yourself, but I think the smoothing is a little better, at least to my eyes.
But I have noticed, the Photon cloud runs faster now. So the 'Interpolation' row looks perfect at the moment.
Also, take out the PrevCorrectPos, I put it in there, but don't use it.
About FixedUpdate() :
Doesn't it do about the same as the regular Update() if you factor-in the time that actually passed since Update()?
I didn't use FixedUpdate() so far. Maybe I should.
now I understand the things behind... thank you very much for explaining that. I played with the new 'CubeLerp' code a bit and found out the problem itself.
When you interpolate by using the time between two movement positions and the start and endpoint, you should never change the starting position during interpolation. When you do this, you'll get always the jerky movement when a object is moving with constant speed.
I have already added the PrevCorrectPos and a modified counter for the time. I used a send rate of 10 times per second. Now I have to add a stack because the end time is not known and cannot be correct, so I have to shift one step behind. That's mostly no problem... for collision detection we can use the Valve technic (collision boxes without interpolation).
All the best,
Klaus
I have also noticed, the time which is is used for interpolation varies a lot. So, we always have to use the correct time for interpolating between two states.
I'll post it when I have solved it before.
That's the reason why the interpolation quality differs... it's depending to the cloud servers. When the following packages is coming too late, the object stays still for one or two frames which causes the jitter in my video. The duration between the jitters matches the serial send rate.
BTW: FixedUpdate cannot solve this. That's only used when you are working with physic calculations and add to the rigidbody a force, velocity, ... I have done some basic checks with 1 package per second... then you see it much better.
All the best,
Klaus
1. fixed update is necessary for smoothing not prediction, and should be used IMHO for the interpolation between packets.
2. the issue of the object pausing when the next packet arrives late is called prediction. My tweak to the Photon sample doesn't provide prediction, but it's easy enough to do. If you don't receive the next packet as expected, then continue interpolating in the same direction, expecting that the player kept moving the same way. If the player stopped or changed direction you'll compensate once the next packet finally arrives.
The problem so far:
While we lerped from our position to the target, we not only increased the fraction (how far we got from A to
This looked bad: The cube moved faster and slowed down, even if updates were relatively constant (timing wise). This was worse when updates came in before we reached the target.
A solution:
When we get an update, we remember "where we are on update" as O and save the "last known position" as B. We also reset how far we got (as our new origin is different).
In the following frames until next update, we have to somehow count up from 0.0f to 1.0f. This can be realized with Update() and deltaTime or FixedUpdate() and it looks relatively smooth.
The current position should be ignored while Lerping from O to B.
This is much better than before.
The new code is attached and will be in next PUN update.
Of course, it's not perfect. In this algorithm, we always change speed of the remote cubes to not fall behind the last update too much.
An alternative would be to fix speed but then maybe never reaching the position we got from last update.