Multiplayer
VehicleController includes built-in multiplayer state synchronization compatible with any networking framework.
Architecture
State Synchronization
The VehicleController.Multiplayer.cs partial class provides:
- GetMultiplayerState(): Captures current vehicle state for network transmission
- SetMultiplayerState(): Applies received state on remote clients
- MultiplayerState struct: Compact data structure containing all synchronized values
Synchronized data:
- Input states (steering, throttle, clutch, handbrake, gear shifts)
- Engine RPM (angular velocity)
- Light states (bit-packed integer)
- Special actions (horn, cruise control, boost, flip over, trailer attach/detach)
MultiplayerIsRemote Property
Set vehicleController.MultiplayerIsRemote = true on non-authoritative clients to:
- Disable local input processing (
input.autoSetInputautomatically disabled) - Allow network state to control the vehicle
- Prevent camera switching on remote vehicles
Physics Synchronization
The multiplayer scripts synchronize vehicle state only, not physics. You must add a physics sync component from your networking framework:
Mirror: NetworkTransformReliable or NetworkRigidbodyReliable PUN2: PhotonTransformView and PhotonRigidbodyView
Supported Frameworks
Official implementations included as samples:
Mirror
Component: MirrorMultiplayerVehicle
Location: Samples~/MultiplayerMirrorSample
Features: Server-validated inputs, 20Hz sync rate, automatic NetworkIdentity setup
Photon Unity Networking 2
Component: PhotonMultiplayerVehicle
Location: Samples~/MultiplayerPUN2Sample
Features: IPunObservable implementation, configurable send/serialization rates
Custom Implementation
To implement for other frameworks:
- Detect ownership/authority in your networking component
- Set
vehicleController.MultiplayerIsRemote = !isOwnedafter initialization - On owned client: Call
GetMultiplayerState()and send via network - On remote clients: Receive state and call
SetMultiplayerState() - Add physics sync component from your framework
Example pseudo-code:
void OnOwnershipDetermined()
{
vehicleController.MultiplayerIsRemote = !IsOwned();
}
void FixedUpdate()
{
if (IsOwned())
{
var state = vehicleController.GetMultiplayerState();
SendToNetwork(state);
}
}
void OnReceiveState(MultiplayerState state)
{
if (!IsOwned())
{
vehicleController.SetMultiplayerState(state);
}
}