257 lines
8.2 KiB
C#
257 lines
8.2 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
[Serializable]
|
|
public class State : System.Object
|
|
{
|
|
public Vector3 p;
|
|
public Quaternion r;
|
|
public float t = 0.0f;
|
|
public float m = 0.0f;
|
|
public float n = 0.0f;
|
|
|
|
public State(Vector3 p, Quaternion r, float t, float m, float n)
|
|
{
|
|
this.p = p;
|
|
this.r = r;
|
|
this.t = t;
|
|
this.m = m;
|
|
this.n = n;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class VehicleNet : MonoBehaviour
|
|
{
|
|
public Vehicle vehicle;
|
|
public bool simulatePhysics = true;
|
|
public bool updatePosition = true;
|
|
public float physInterp = 0.1f;
|
|
public float ping;
|
|
public float jitter;
|
|
public float calcPing = 0.00f;
|
|
public float rpcPing = 0.00f;
|
|
public float lastPing = -1.00f;
|
|
public int pingCheck;
|
|
public bool wePinged = false;
|
|
public float autoInterp = 0.00f;
|
|
private int m;
|
|
private Vector3 p;
|
|
private Quaternion r;
|
|
public State[] states;
|
|
|
|
public VehicleNet()
|
|
{
|
|
pingCheck = UnityEngine.Random.Range(15, 20);
|
|
states = new State[15];
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
vehicle.networkView.observed = this;
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (vehicle.networkMode == 2 && Time.time > lastPing + (float)pingCheck)
|
|
{
|
|
if (lastPing < 0f)
|
|
{
|
|
lastPing = Time.time;
|
|
}
|
|
else
|
|
{
|
|
networkView.RPC("sT", RPCMode.All, 0f);
|
|
}
|
|
}
|
|
|
|
if (
|
|
!updatePosition ||
|
|
states[14] == null ||
|
|
states[14].t == 0f ||
|
|
!vehicle.myRigidbody ||
|
|
!Game.Player ||
|
|
!Game.Player.rigidbody)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Game.Settings.networkPhysics == 0)
|
|
{
|
|
physInterp = 0.1f;
|
|
}
|
|
else if (Game.Settings.networkPhysics == 1)
|
|
{
|
|
physInterp = 0.2f;
|
|
}
|
|
|
|
if (Game.Settings.networkPhysics == 2)
|
|
{
|
|
simulatePhysics = false;
|
|
}
|
|
else
|
|
{
|
|
simulatePhysics = Vector3.Distance(
|
|
vehicle.myRigidbody.position,
|
|
Game.Player.rigidbody.position) < 40f;
|
|
}
|
|
|
|
vehicle.myRigidbody.isKinematic = !simulatePhysics;
|
|
vehicle.myRigidbody.interpolation = RigidbodyInterpolation.None;
|
|
|
|
//Interpolation
|
|
float interpolationTime;
|
|
if (Game.Settings.networkInterpolation > 0f)
|
|
{
|
|
interpolationTime = (float)(Network.time - (double)Game.Settings.networkInterpolation);
|
|
}
|
|
else
|
|
{
|
|
autoInterp = Mathf.Max(
|
|
0.1f,
|
|
Mathf.Lerp(
|
|
autoInterp,
|
|
ping * 1.5f + jitter * 8f,
|
|
Time.deltaTime * 0.15f));
|
|
interpolationTime = (float)(Network.time - (double)autoInterp);
|
|
}
|
|
|
|
if (states[0].t > interpolationTime) // Target playback time should be present in the buffer
|
|
{ // Go through buffer and find correct state to play back
|
|
for (int i = 1; i < states.Length - 1; i++)
|
|
{
|
|
if (
|
|
states[i] != null &&
|
|
states[i].t <= interpolationTime ||
|
|
i == states.Length - 3)
|
|
{
|
|
State rhs = states[i - 1]; // The state one slot newer than the best playback state
|
|
State lhs = states[i]; // The best playback state (closest to .1 seconds old)
|
|
float l = rhs.t - lhs.t; // Use the time between the two slots to determine if interpolation is necessary
|
|
float t = 0f; // As the time difference gets closer to 100 ms, t gets closer to 1 - in which case rhs is used
|
|
if (l > 0.0001f)
|
|
{
|
|
t = (interpolationTime - lhs.t) / l; // if t=0 => lhs is used directly
|
|
}
|
|
vehicle.velocity = Vector3.Lerp(
|
|
vehicle.velocity,
|
|
((rhs.p - states[i + 2].p) / (rhs.t - states[i + 2].t)),
|
|
Time.deltaTime * 0.3f);
|
|
if (simulatePhysics)
|
|
{
|
|
vehicle.myRigidbody.MovePosition(Vector3.Lerp(
|
|
vehicle.transform.position,
|
|
Vector3.Lerp(lhs.p, rhs.p, t),
|
|
physInterp));
|
|
vehicle.myRigidbody.MoveRotation(Quaternion.Slerp(
|
|
vehicle.transform.rotation,
|
|
Quaternion.Slerp(lhs.r, rhs.r, t),
|
|
physInterp));
|
|
vehicle.myRigidbody.velocity = vehicle.velocity;
|
|
}
|
|
else
|
|
{
|
|
vehicle.myRigidbody.position = Vector3.Lerp(lhs.p, rhs.p, t);
|
|
vehicle.myRigidbody.rotation = Quaternion.Slerp(lhs.r, rhs.r, t);
|
|
}
|
|
vehicle.isResponding = true;
|
|
vehicle.netCode = "";
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Extrapolations
|
|
else
|
|
{
|
|
float extrapolationLength = (interpolationTime - states[0].t);
|
|
vehicle.velocity = Vector3.Lerp(
|
|
vehicle.velocity,
|
|
((states[0].p - states[2].p) / (states[0].t - states[2].t)),
|
|
Time.deltaTime * 0.3f);
|
|
if (extrapolationLength < 1f)
|
|
{
|
|
if (!simulatePhysics)
|
|
{
|
|
vehicle.myRigidbody.position = states[0].p +
|
|
(vehicle.velocity * extrapolationLength);
|
|
vehicle.myRigidbody.rotation = states[0].r;
|
|
}
|
|
vehicle.isResponding = true;
|
|
if (extrapolationLength < 0.3f) vehicle.netCode = ">";
|
|
else vehicle.netCode = " (Delayed)";
|
|
}
|
|
else
|
|
{
|
|
vehicle.netCode = " (Not Responding)";
|
|
vehicle.isResponding = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
|
|
{
|
|
//We are the server, and have to keep track of relaying messages between connected clients
|
|
if (stream.isWriting)
|
|
{
|
|
if (networkView.stateSynchronization == NetworkStateSynchronization.Off)
|
|
{
|
|
Debug.Log("sNv NvS: " + gameObject.name);
|
|
return;
|
|
}
|
|
|
|
if (states[0] == null) return;
|
|
p = states[0].p;
|
|
r = states[0].r;
|
|
//m is the number of milliseconds that transpire between the packet's original send time and the time it is resent from the server to all the other clients
|
|
m = (int)((Network.time - (double)states[0].t) * 1000.0);
|
|
stream.Serialize(ref p);
|
|
stream.Serialize(ref r);
|
|
stream.Serialize(ref m);
|
|
}
|
|
|
|
//New packet recieved - add it to the states array for interpolation!
|
|
else
|
|
{
|
|
if (networkView.stateSynchronization == NetworkStateSynchronization.Off)
|
|
{
|
|
Debug.Log("sNv NvN: " + gameObject.name);
|
|
return;
|
|
}
|
|
|
|
stream.Serialize(ref p);
|
|
stream.Serialize(ref r);
|
|
stream.Serialize(ref m);
|
|
|
|
State state = new State(
|
|
p,
|
|
r,
|
|
(float)(info.timestamp - (double)((m <= 0) ?
|
|
0f :
|
|
((float)m / 1000f))),
|
|
m,
|
|
(float)(Network.time - info.timestamp));
|
|
|
|
if (states[0] != null && state.t == states[0].t)
|
|
{
|
|
state.t += 0.01f; //Bizarre - dragonhere
|
|
}
|
|
|
|
if (states[0] == null || state.t > states[0].t)
|
|
{
|
|
float png = (float)(Network.time - (double)state.t);
|
|
jitter = Mathf.Lerp(
|
|
jitter,
|
|
Mathf.Abs(ping - png),
|
|
1f / Network.sendRate);
|
|
ping = Mathf.Lerp(ping, png, 1f / Network.sendRate);
|
|
for (int k = states.Length - 1; k > 0; k--)
|
|
{
|
|
states[k] = states[k - 1];
|
|
}
|
|
states[0] = state;
|
|
}
|
|
}
|
|
}
|
|
}
|