Hello!
Ive been working on making a multiplayer driving sumo-wrestling game. Ive been working on a couple implementations to sync the players in my game. The players are all rigidbodies and need to respond to collisions with other players.
I started with a Sever Authoritative approach, but found this lacking and controlling the car wasn’t responsive enough.
So I’ve switched to a Client Authoritative approach. I plan on handling collision calculations on the server, and then sending the results to the clients so the proper collision forces can be applied. This is where I am having trouble. The rigid bodies do not respond to any force applied to them!
I have some debugging statements included in this block and I can confirm that after a collision I see the an appropriate force vector logged on the client session.
So what can I be missing? Is there a proper way for the server to apply force to a game object? I understand with this model, the server can not directly change the client position, but shouldn’t a ClientRpc allow the client to make this adjustment. I feel like I am misunderstanding something in the configuration of my Network Objects
Here is a sample from the Controller Script and the network objects on my Player.
private void OnCollisionEnter(Collision collision)
{
collision.gameObject.TryGetComponent<HogController>(out HogController collisionTarget);
if (IsServer && collisionTarget != null)
{
// Get the NetworkRigidbody components
Rigidbody rb1 = rb;
Rigidbody rb2 = collision.gameObject.GetComponent<Rigidbody>();
CarState collisionTargetState = collisionTarget.GetClientState();
// Calculate the relative velocity
Vector3 relativeVelocity = state.peakVelocity - collisionTargetState.peakVelocity;
// Calculate the masses
float mass1 = rb1.mass;
float mass2 = rb2.mass;
// Calculate the impulse
Vector3 impulse1 = (mass2 * relativeVelocity) / (mass1 + mass2);
Vector3 impulse2 = -impulse1;
ulong player1Id = GetComponent<NetworkObject>().OwnerClientId;
ulong player2Id = collision.gameObject.GetComponent<NetworkObject>().OwnerClientId;
Debug.Log(message:
"Collision detected between " + ConnectionManager.instance.GetClientUsername(player1Id)
+ " and " + ConnectionManager.instance.GetClientUsername(player2Id)
);
Debug.Log("Collision Relative Velocity - " + relativeVelocity);
// Notify clients about the collision and applied force
ApplyCollisionForceClientRpc(player1Id, impulse2);
ApplyCollisionForceClientRpc(player2Id, impulse1);
}
}
[ClientRpc]
private void ApplyCollisionForceClientRpc(ulong clientId, Vector3 force)
{
if (IsOwner && clientId == GetComponent<NetworkObject>().OwnerClientId)
{
Debug.Log(message:
"Applying collision force of " + force * additionalCollisionForce + " to " + ConnectionManager.instance.GetClientUsername(clientId)
);
var client = NetworkManager.Singleton.ConnectedClients[clientId];
client.PlayerObject.GetComponent<Rigidbody>().AddForce(force * additionalCollisionForce, ForceMode.Impulse);
}
}
Unity v6000.0.33f1 - NGO v2.2.0