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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
	}
 | 
						|
}
 |