How can I do collisions over a network?

Hi all!

So basically, I have a listen server atm and I have it so it spawns a car (uses edy’s vehicle physics) whenever the server is created, and another one whenever the client connects. The positions and rotations update fine, and collisions work as long as the car is going slow. But if I run one car into the other at high speed, that car will go flying into space; while the other car (stationary car that got hit) acts as an immovable object. I looked around and I couldn’t seem to find a good way to do collision on a network. Here is my networking code as of right now:

public class ClientPrediction : MonoBehaviour {

	    float interpolationBackTime = 0.1f;
         class State
    {
        public float timeStamp;
        public Vector3 pos;
        public Quaternion rot;
    }
    private State[] m_BufferedState = new State[20]; // where we store the State of our controller
    private int m_TimestampCount; // keeps track of what slots are used
     
     
    // Holds information about the controllers movements and last sent information from the network

      void OnNetworkInstantiate(NetworkMessageInfo info)
	{
        if(networkView.isMine)
		{ //if I am the owner of this prefab
            Camera.main.GetComponent<SmoothFollow>().target = transform;
        }
    }
    void OnSerializeNetworkView(BitStream stream,NetworkMessageInfo info)
    {
		Vector3 pos;
		Quaternion rot;
        if (stream.isWriting)
        {
             pos = transform.position;
             rot = transform.rotation;
           
            stream.Serialize(ref pos);
            stream.Serialize(ref rot);
        }
        else
        {
            pos = Vector3.zero;
            rot = Quaternion.identity;
            stream.Serialize(ref pos);
            stream.Serialize(ref rot);
           
           
            for (var i = m_BufferedState.Length - 1; i >= 1; i --)
            {
                m_BufferedState *= m_BufferedState[i-1];*

}

State state = new State();
state.timeStamp = (float)info.timestamp;
state.pos = pos;
state.rot = rot;
m_BufferedState[0] = state;

m_TimestampCount = Mathf.Min(m_TimestampCount + 1, m_BufferedState.Length);

for (int i = 0; i < m_TimestampCount-1; i++)
{
if (m_BufferedState*.timeStamp < m_BufferedState[i+1].timeStamp)
_
{_
Debug.Log(“State inconsistent”);
_
}_
_
}_
_
}_
_
}*_

void Update ()
{
if (!networkView.isMine)
{
float currentTime = (float)Network.time;
float interpolationTime = currentTime - interpolationBackTime;

if (m_BufferedState[0] != null && m_BufferedState[0].timeStamp > interpolationTime)
{
for (var i = 0; i < m_TimestampCount; i++)
{
if (m_BufferedState*.timeStamp <= interpolationTime || i == m_TimestampCount - 1)
_{
// The state one slot newer (<100ms) than the best playback state*
State rhs = m_BufferedState[Mathf.Max(i-1, 0)];
// The best playback state (closest to 100 ms old (default time))_

State lhs = m_BufferedState*;*

// Use the time between the two slots to determine if interpolation is necessary
float length = rhs.timeStamp - lhs.timeStamp;
float t = 0.0f;

if (length > 0.0001)
{
t = ((interpolationTime - lhs.timeStamp) / length);
}

// if t=0 => lhs is used directly
transform.position = Vector3.Lerp(lhs.pos, rhs.pos, t);
transform.rotation = Quaternion.Slerp(lhs.rot, rhs.rot, t);
return;

}
}
}
else
{
if (m_BufferedState[0] != null)
{
State latest = m_BufferedState[0];
transform.position = latest.pos;
transform.rotation = latest.rot;
}
}
}
}
}
So there is the stuff that does the client prediction, I got this script from somebody on the unity forums and it works great! But as you can see its only predicting for position and rotation. I’m new to networking so I’m unsure how to proceed with collisions. For now all the computations are done client side since I only have a listen server implemented. Any ideas on how I could get collisions to work over a network?
Thanks

Anybody? It seems like this would be a common problem for multiplayer games that use unity...

Have you read this? http://docs.unity3d.com/Documentation/Components/net-StateSynchronization.html

All your collision work needs to be done on at least one side of the network. I suggest an Authoritative server system :)

Okay thanks! So I switched my stuff to an authoritative server system, but how do I do the collision work? I thought all that stuff is calculated some where in unityengine dlls or something. All I kno about is OnCollisionEnter/Stay/Exit and I'm not sure how I would use those.

The standard "collision work" is done by Unity, however you can implement stuff yourself. The extra work you need to depends entirely on what your collisions cause and how your multiplayer is setup.

1 Answer

1

If you’re using physics, you shouldn’t do collisions ‘over the network’.

What you should do is have an authoritative server that does all the physics calculations and sends the resulting transforms of these collisions to all clients. If you have multiple physics calculations going on in multiple clients, things can get messy.

The solution was a mixture of this, setting collision on rigid bodies to continuous dynamic, and up scaling the objects.

Is there a tutorial for how to setup this authoritative server or any resources that could be helpful? Thanks, Jason