Added lag compensation

This commit is contained in:
Albin Corén 2018-03-04 17:54:10 +01:00
parent 8484ed77e1
commit 90ab0cf020
5 changed files with 136 additions and 2 deletions

View File

@ -23,6 +23,7 @@ namespace MLAPI
public bool ConnectionApproval = false;
public Action<byte[], int, Action<int, bool>> ConnectionApprovalCallback = null;
public byte[] ConnectionData = new byte[0];
public float SecondsHistory = 5;
public bool HandleObjectSpawning = true;
//TODO
public bool CompressMessages = false;

View File

@ -0,0 +1,10 @@
using UnityEngine;
namespace MLAPI.Data
{
internal struct TrackedPointData
{
internal Vector3 position;
internal Quaternion rotation;
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using UnityEngine.Networking;
namespace MLAPI.MonoBehaviours.Core
{
public static class LagCompensationManager
{
public static List<TrackedObject> SimulationObjects = new List<TrackedObject>();
public static void Simulate(float secondsAgo, Action action)
{
for (int i = 0; i < SimulationObjects.Count; i++)
{
SimulationObjects[i].ReverseTransform(secondsAgo);
}
action.Invoke();
for (int i = 0; i < SimulationObjects.Count; i++)
{
SimulationObjects[i].ResetStateTransform();
}
}
private static byte error = 0;
public static void Simulate(int clientId, Action action)
{
float milisecondsDelay = NetworkTransport.GetCurrentRTT(NetworkingManager.singleton.hostId, clientId, out error) / 2f;
Simulate(milisecondsDelay * 1000f, action);
}
internal static void AddFrames()
{
for (int i = 0; i < SimulationObjects.Count; i++)
{
SimulationObjects[i].AddFrame();
}
}
}
}

View File

@ -1,4 +1,5 @@
using MLAPI.NetworkingManagerComponents;
using MLAPI.MonoBehaviours.Core;
using MLAPI.NetworkingManagerComponents;
using System;
using System.Collections;
using System.Collections.Generic;
@ -255,7 +256,7 @@ namespace MLAPI
}
//Receive stuff
int hostId;
internal int hostId;
int clientId;
int channelId;
int receivedSize;
@ -328,6 +329,7 @@ namespace MLAPI
(messagesProcessed < NetworkConfig.MaxMessagesPerFrame || NetworkConfig.MaxMessagesPerFrame < 0));
}
LagCompensationManager.AddFrames();
}
private IEnumerator ApprovalTimeout(int clientId)

View File

@ -0,0 +1,80 @@
using MLAPI.Data;
using System.Collections.Generic;
using UnityEngine;
namespace MLAPI.MonoBehaviours.Core
{
//Based on: https://twotenpvp.github.io/lag-compensation-in-unity.html
//Modified to be used with latency rather than fixed frames and subframes. Thus it will be less accrurate but more modular.
public class TrackedObject : MonoBehaviour
{
internal Dictionary<float, TrackedPointData> FrameData = new Dictionary<float, TrackedPointData>();
internal List<float> Framekeys = new List<float>() { 0 };
private Vector3 savedPosition;
private Quaternion savedRotation;
internal void ReverseTransform(float secondsAgo)
{
savedPosition = transform.position;
savedRotation = transform.rotation;
float currentTime = Time.time;
float targetTime = Time.time - secondsAgo;
float previousTime = 0;
float nextTime = 0;
for (int i = 1; i < Framekeys.Count - 1; i++)
{
if(Framekeys[i - 1] > targetTime && Framekeys[i] <= targetTime)
{
previousTime = Framekeys[i];
nextTime = Framekeys[i + 1];
break;
}
}
float timeBetweenFrames = nextTime - previousTime;
float timeAwayFromPrevious = currentTime - previousTime;
float lerpProgress = timeAwayFromPrevious / timeBetweenFrames;
transform.position = Vector3.Lerp(FrameData[previousTime].position, FrameData[nextTime].position, lerpProgress);
transform.rotation = Quaternion.Slerp(FrameData[previousTime].rotation, FrameData[nextTime].rotation, lerpProgress);
}
internal void ResetStateTransform()
{
transform.position = savedPosition;
transform.rotation = savedRotation;
}
void Start()
{
LagCompensationManager.SimulationObjects.Add(this);
}
void OnDestroy()
{
LagCompensationManager.SimulationObjects.Remove(this);
}
internal void AddFrame()
{
float currentTime = Time.time;
for (int i = 0; i < Framekeys.Count; i++)
{
if (currentTime - Framekeys[i] <= NetworkingManager.singleton.NetworkConfig.SecondsHistory)
{
for (int j = 0; j < i; j++)
{
FrameData.Remove(Framekeys[0]);
//This is not good for performance. Other datatypes should be concidered.
Framekeys.RemoveAt(0);
}
}
}
FrameData.Add(Time.time, new TrackedPointData()
{
position = transform.position,
rotation = transform.rotation
});
Framekeys.Add(Time.frameCount);
}
}
}