- Home /
Lag Compensation with Photon Unity Networking
Hello everybody! I'm trying to make a multiplayer 2D shooter game and I've decided on using Photon. The issue I'm having is that remote characters' movements are choppy, but then if I lerp them they become floaty, and "glide" toward the ground (for lack of a better word) after a jump. Does anyone know of a way to mitigate this floatiness or of a better way to go about smoothing network movements?
This is the current script I have attached to the characters:
using UnityEngine;
using System.Collections;
public class NetworkPlayer : Photon.MonoBehaviour
{
public Vector3 realPosition = Vector3.zero;
public float speed = .1f;
void Update ()
{
if (!photonView.isMine)
{
transform.position = Vector3.MoveTowards(transform.position, realPosition, speed);
}
}
void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.isWriting)
{
stream.SendNext((Vector3)transform.position);
}
else
{
realPosition = (Vector3)stream.ReceiveNext();
}
}
}
Thanks! Bentley
Answer by Bentley · Jan 02, 2015 at 09:29 AM
Of course right after I ask the question I finally find an answer. This is my updated script. It seems smooth enough for my purposes and there are no more adverse lerp side effects. Hopefully someone else can find a use for this in the future.
using UnityEngine;
using System.Collections;
public class NetworkPlayer : Photon.MonoBehaviour
{
public Vector3 realPosition = Vector3.zero;
public Vector3 positionAtLastPacket = Vector3.zero;
public double currentTime = 0.0;
public double currentPacketTime = 0.0;
public double lastPacketTime = 0.0;
public double timeToReachGoal = 0.0;
void Update ()
{
if (!photonView.isMine)
{
timeToReachGoal = currentPacketTime - lastPacketTime;
currentTime += Time.deltaTime;
transform.position = Vector3.Lerp(positionAtLastPacket, realPosition, (float)(currentTime / timeToReachGoal));
}
}
void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.isWriting)
{
stream.SendNext((Vector3)transform.position);
}
else
{
currentTime = 0.0;
positionAtLastPacket = transform.position;
realPosition = (Vector3)stream.ReceiveNext();
lastPacketTime = currentPacketTime;
currentPacketTime = info.timestamp;
}
}
}
Yes this is the solution. But isn't this just "hiding" the lag? You're only showing an movement between the synchronizing to smooth the visuals. But the actual positions are only updating during the synchronizing. Which means if you're going to create a game where you need some quick reactions (Like an fps game or moba), then the game wouldn't be able to "smooth" out quick turnarounds, since the velocity isn't staying the same so that you are able to predict their movements. $$anonymous$$y photon network project has 6 frames lag between the synchronizing. I can make the movements look smooth, but you can't at all create the quick reactions game I wanted to make. Anyone know any solution to fix the actual lag?
Hi $$anonymous$$eseren,
I haven't quite found a solution that is elegant. However, what I did was measure if the SyncTime has surpassed the delay, when it is expecting the next position. Then if that's the case, in update, the player controlling the object sends a position RPC update. It's a bit hacky, and may potentially lead to the message / second issue if lag is serious. I copied the parts of the script that refer to the RPC sync position when 'needed'
[PunRPC]
public void DelayedPlayerPacketSyncPosition(){
realPosition = tr.position;
}
void Update {
if ( photonView.is$$anonymous$$ine ) {
//Do nothing -- the character motor/input/etc.. is moving us
if(syncTime > (syncDelay * 1f)){
GetComponent<PhotonView> ().RPC ("DelayedPlayerPacketSyncPosition", PhotonTargets.AllBuffered);
}
}
}
Have you come across any other work arounds in the mean time?
Oh one more comment, I haven't done it yet, but was thinking of one extra smoothing step, is for those players who are not controlling the object. When the syncTime has exceeded, for those guys, they lerp the current position, to the RPCPostion sent by the controlling player.
The effect without this lerp is, the lag becomes significantly shorter than what it was before. Now I want to see if in between these lags, I can smooth them out further. Still testing the RPC count on a decent load fps game 2 players, 3 bots on each $$anonymous$$m (controlled by master client) - Was clocking in at around 180 messages / second in that room. So, not yet the 500 soft limit, which is a good sign, to host smaller scale games.
It doesn't have a significant affect on messages per second before and after. ($$anonymous$$ost of the messages I mentioned previously came from the actual game events, shooting, spawning, etc...)
So from massive lags, dee$$anonymous$$g the online play almost unplayable, and frustrating, the movements are now a lot smoother and when it does lag, the choppiness is much less, though noticeable, but perhaps acceptable for online play.
I am also sending onserialize updates at a rate of 20 per second, and a general sendrate of 33 per second.
Answer by ragnaken · Mar 22, 2017 at 07:18 AM
thanks, when i saw your code i realised that i have a similar script from photon examples, that is almost the same, then i use it and goes perfect. no more lag. Marcopolotutorial -> NetworkCharacter.cs
Your answer
