Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

What should I use for a 1v1 racing game?

Discussion in 'Multiplayer' started by 0x00000F, Jul 4, 2014.

  1. 0x00000F

    0x00000F

    Joined:
    Jun 16, 2014
    Posts:
    16
    Hey
    I will make a 1v1 (multiplayer) racing game for Android and I don't know what should I use?
    I've tried Google Play Games plugin but it's not useful to send positions and rotations.
    I tried Bolt networking too but it is complicated and there is no tutorial or sth.

    What should I use? I just want a auto-match system like Google's, not lobby.
     
  2. BFGames

    BFGames

    Joined:
    Oct 2, 2012
    Posts:
    1,543
  3. 0x00000F

    0x00000F

    Joined:
    Jun 16, 2014
    Posts:
    16
  4. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,958
    Use default Unity Networking. It's best for small scale MP. I assume you're using Rigidbody and Wheel collider to simulate vehicle driveability. Look for the Multiplayer v3 pdf, in there you will find a script for interpolating a rigidbody over a network(for your partner in MP). You could then create scripts for your tyres to inherit rotation as a function of the car's movement, which is derived from the Network rigidbody interpolation. You don't need any plugin for this. Unity's networking is very packet efficient (RDCompressed networkView) with small amounts of network players.
     
  5. 0x00000F

    0x00000F

    Joined:
    Jun 16, 2014
    Posts:
    16
    Thank you for your advice.
    But I guess I read in somewhere Unity Networking doesn't support cell network.

    Also I saw this game is using Google Play Games in multiplayer mode. I said GPG is not useful(in first post) but it must be from my incompetence.
     
  6. Navy_King

    Navy_King

    Joined:
    Jul 7, 2014
    Posts:
    2
    I'm making multiplayer racing game,too.I've finished a simple one,but the position of the cars don't synchronized well.My method just like the 4th post said.Any questions or advices please sent to my email:wangzi371312@163.com
     
  7. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,958
    Navy_King, are you using Transform interpolation or Rigidbody interpolation? Check that your Network Views are on Reliable Delta Compressed instead of Unreliable. And make sure that your group 0 gameobjects have their position (not localPosition) synchronized. I've faced similar problems like these.
     
  8. Navy_King

    Navy_King

    Joined:
    Jul 7, 2014
    Posts:
    2
    hi,I have used skills just like Rigidbody interpolation in fixedupdate.Trouble is that when the car is driving in a low speed or the distance between two cars is large,I can see a smoothly moving parter.Well,when two cars are very close,my partner's car isn't synchronized well.

    Code (CSharp):
    1. function FixedUpdate()
    2. {  
    3.     if(networkView.isMine)
    4.     {
    5.         // The rigidbody velocity is always given in world space, but in order to work in local space of the car model we need to transform it first.
    6.         var relativeVelocity : Vector3 = transform.InverseTransformDirection(rigidbody.velocity);  
    7.         CalculateState();      
    8.         UpdateFriction(relativeVelocity);  
    9.         UpdateDrag(relativeVelocity);  
    10.         CalculateEnginePower(relativeVelocity);  
    11.         ApplyThrottle(canDrive, relativeVelocity);  
    12.         ApplySteering(canSteer, relativeVelocity);
    13.     }
    14.     else
    15.     {
    16.         syncTime += Time.deltaTime;      
    17.         rigidbody.MovePosition(Vector3.Lerp(syncStartPosition, syncEndPosition, syncTime / syncDelay));
    18.         rigidbody.MoveRotation(Quaternion.Lerp(rBegin, rEnd, syncTime / syncDelay));
    19.        
    20.        
    21.     }
    I interpolate car's rigidbody position and rotation directly,not tyres' as 4th post said.Does this matter?
     
  9. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,958
    Hey Navy_King. If I were in your shoes, I wont do Rigidbody interpolation. This is what I'll do:

    //----------------------------------------------------------
    -I am Player A
    -Other person is Player B
    //----------------------------------------------

    PROBLEM:
    Come up with a way to Net Sync myself (A) on B's game and vice versa

    SETUP:
    I have (I'm assuming you have this) a car setup with the car mesh using a collider-Rigidbody and wheel colliders with wheel meshes attached and setup to create propulsion through WheelCollider.motorTorque. (Please correct me here if I'm wrong as I dont know your setup)

    SYNC:
    Let us assume that we're on Player B's device and playing with Player A. I want to sync Player A's position, rotation, wheel rotation, and front wheel steer angle with Player A's instance on Player B's device. Let's break this down into 3:

    1. Position & Rotation-
    -Set player A's rigidbody on Player B's device to kinematic
    Code (JavaScript):
    1. //Use this script on Player A
    2.  
    3. function Start() { //or whatever function you wish to use to perform this check
    4.  
    5. if (!networkView.isMine) {
    6. rigidbody.IsKinematic = true;
    7. (gameObject.GetComponent("NetworkInterpolatedTransform") as NetworkInterpolatedTransform).enabled = true; //Look below to understand why I did this ^
    8. }
    9. }
    -Use NetworkInterpolatedTransform (yes, not rigidbody) to send transform data. Apply this script to Player A's instance
    Code (JavaScript):
    1. //This is the javascript version I converted myself to fit your needs ^.^
    2. var interpolationBackTime : double = 0.1;
    3. //var ExtrapolationLimit : double = 0.5;
    4.  
    5. public class State extends System.ValueType {
    6.     var timeStamp : double;
    7.     var pos : Vector3;
    8.     var rot : Quaternion;
    9.     var frontWheelAngle : float;
    10. }
    11.  
    12. var m_BufferedState : State[] = new State[20];
    13.  
    14. private var m_TimestampCount : int;
    15.  
    16. function OnSerializeNetworkView (stream : BitStream, info : NetworkMessageInfo) {
    17.  
    18.     //If we're the one writing info to the network
    19.     if (stream.isWriting) {
    20.         var pos : Vector3 = transform.position;
    21.         var rot : Quaternion = transform.rotation;
    22.         var frontWheelAngle = transform.Find([one of your front wheels]).rotation.y;
    23.         stream.Serialize(pos);
    24.         stream.Serialize(rot);
    25.         stream.Serialize(frontWheelAngle);
    26.     }
    27.  
    28.     //when we're recieving info of our clients
    29.     else {
    30.         pos = Vector3.zero;
    31.         rot = Quaternion.identity;
    32.         frontWheelAngle = 0;
    33.         stream.Serialize(pos);
    34.         stream.Serialize(rot);
    35.         stream.Serialize(frontWheelAngle);
    36.     }
    37.  
    38.     //Shift buffer contents, oldest data erased
    39.     for (var i : int = m_BufferedState.Length-1 ; i>=1; i--) {
    40.         m_BufferedState[i] = m_BufferedState[i-1];
    41.     }
    42.  
    43.     //Save current recieved state as 0 in the buffer, safe to overwrite after shifting
    44.     var state : State;
    45.     state.timeStamp = info.timestamp;
    46.     state.pos = pos;
    47.     state.rot = rot;
    48.     state.frontWheelAngle = frontWheelAngle;
    49.     m_BufferedState[0] = state;
    50.  
    51.     //Increment state count but never exceed buffer size
    52.     m_TimestampCount = Mathf.Min(m_TimestampCount+1, m_BufferedState.Length);
    53.  
    54.     //Check integrity, lowest numbered state in the buffer is the newest and so on
    55.     for (i = 0; i<m_TimestampCount-1; i++) {
    56.         if (m_BufferedState[i].timeStamp < m_BufferedState[i+1].timeStamp) {
    57.             Debug.Log("State inconsistent");
    58.         }
    59.     }
    60.  
    61.     //Debug.Log("stamp: " + info.timestamp + " My time: " + Network.time + " delta: " + (Network.time-info.timestamp));
    62.  
    63. }
    64.  
    65. function Update() {
    66. //This only runs when the component is enabled on remote clients (servers, clients)
    67.  
    68.     var currentTime : double = Network.time;
    69.     var interpolationTime : double = currentTime - interpolationBackTime;
    70.  
    71.     // We have a window of interpolation time that we play
    72.     //By having interpolationBackTime the average ping, you will usually use interpolation
    73.     //And only if no more data arrives will we use extrapolation
    74.  
    75.     //Use interpolation
    76.     //Check if latest state exceeds interpolation time
    77.     //If this is the case then it is too old and extrapolation should be used
    78.  
    79.     if (m_BufferedState[0].timeStamp > interpolationTime) {
    80.  
    81.         for (var i : int = 0; i<m_TimestampCount;i++) {
    82.          
    83.             //Find a state that matches the interpolation time (time+.1) or use the last state
    84.             if (m_BufferedState[i].timeStamp   <= interpolationTime || i == m_TimestampCount-1) {
    85.                  
    86.                     //The state one slot newer (<100ms) than the best playback time
    87.                     var rhs : State = m_BufferedState[Mathf.Max(i-1, 0)];
    88.                     //The best playback state (closest to 100ms old (default time))
    89.                     var lhs : State = m_BufferedState[i];
    90.                  
    91.                     //Use the time between the two slots to determine if interpolation is necessary
    92.                     var length : double = rhs.timeStamp - lhs.timeStamp;
    93.                     var t : float = 0;
    94.                  
    95.                     //As the time gets closer to 100ms, t gets closer to 1 in which case only rhs is used
    96.                     if (length > 0.0003) {
    97.                         t = ((interpolationTime - lhs.timeStamp)/length);
    98.                     }
    99.                  
    100.                     //if t = 1 => lhs is used directly
    101.                     transform.position = Vector3.Slerp(lhs.pos, rhs.pos, t);
    102.                     transform.localRotation = Quaternion.Slerp(lhs.rot, rhs.rot, t);
    103.                     transform.Find([front left wheel]).localRotation += Quaternion.Slerp(Quaternion.Euler(0, lhs.frontWheelAngle, 0), Quaternion.Euler(0, rhs.frontWheelAngle,0), t) ;
    104.                     transform.Find([front right wheel]).localRotation += Quaternion.Slerp(Quaternion.Euler(0, lhs.frontWheelAngle, 0), Quaternion.Euler(0, rhs.frontWheelAngle,0), t) ;
    105.  
    106. //not sure if you can add quaternions, so fix as necessary
    107.                     return;
    108.                    
    109.             }
    110.          
    111.         }
    112.      
    113.     }
    114.  
    115.     else {
    116.         var latest : State = m_BufferedState[0];
    117.         transform.position = latest.pos;
    118.         transform.localRotation = latest.rot;
    119.         transform.Find([front left wheel]).localRotation += Quaternion.Euler(0, latest.frontWheelAngle, 0);
    120.         transform.Find([front right wheel]).localRotation += Quaternion.Euler(0, latest.frontWheelAngle, 0);
    121.     }
    122. }
    123.  
    -Now play with interpolationBackTime to suit your network requirements until you have smooth movements.

    2.WheelRotation
    This is where you have to calculate. Look at your car setup and setup an expression for how many tire rotations happen for each world unit the car moves on it's local z axis. Now integrate this value to NIT above and use it to rotate all tires. If you dont understand this step, tell me.

    3. Front wheel y rotation (steerAngle)
    Already included that in NIT above. It may require fixing though :)

    //--------------------------------------------------------------------------------------------

    As I've said, this is what i'd do if i was in your shoes. So yeah,, tell me if you encounter any problems while implementing this solution