Search Unity

Trying Out Physics.Simulate()...

Discussion in 'Multiplayer' started by Jick87, Jul 27, 2017.

  1. Jick87

    Jick87

    Joined:
    Oct 21, 2015
    Posts:
    124
    So I was doing some experimentation with the new Physics.Simulate trying to get some networking with reconciliation working. It doesn't quite work however. So I was wondering if perhaps I was missing something or not doing something correctly.

    Here is the code I was trying:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using UnityEngine;
    5. using UnityEngine.Networking;
    6.  
    7. [RequireComponent(typeof(NetworkIdentity))]
    8. [NetworkSettings(channel=Channels.DefaultReliable,sendInterval=0.1f)]
    9. public class NetworkMovement : NetworkBehaviour
    10. {
    11.     public Camera Camera;
    12.     public Rigidbody MainRigidbody;
    13.     public float InputVertical = 0f;
    14.     public float InputHorizontal = 0f;
    15.     public bool InputSprint = false;
    16.     public bool InputJump = false;
    17.     public bool InputAction = false;
    18.     public Vector3 CameraForward = Vector3.zero;
    19.     public Vector3 CameraRight = Vector3.zero;
    20.     [SyncVar] public float NetworkInputVertical = 0f;
    21.     [SyncVar] public float NetworkInputHorizontal = 0f;
    22.     [SyncVar] public bool NetworkInputSprint = false;
    23.     [SyncVar] public bool NetworkInputJump = false;
    24.     [SyncVar] public bool NetworkInputAction = false;
    25.     [SyncVar] public Vector3 NetworkInputCameraForward = Vector3.zero;
    26.     [SyncVar] public Vector3 NetworkInputCameraRight = Vector3.zero;
    27.     public float NetworkPositionSmoothTime = 0.1f;
    28.     public float NetworkRotationSmoothTime = 0.1f;
    29.     public List<ClientInputSnapshot> NetworkInputHistory = new List<ClientInputSnapshot>();
    30.     public List<ServerResponse> NetworkServerResponseHistory = new List<ServerResponse>();
    31.     [SyncVar] public float ServerSendInterval = 0.5f;
    32.     [HideInInspector] private float _lastInputTime = 0f;
    33.     [HideInInspector] private float _lastSendTime = 0f;
    34.  
    35.     [Command(channel=Channels.DefaultUnreliable)]
    36.     private void CmdSendStateToServer( float vertical, float horizontal, bool sprint, bool jump, bool action, Vector3 camFwd, Vector3 camRght, float time )
    37.     {
    38.         NetworkInputVertical = vertical;
    39.         NetworkInputHorizontal = horizontal;
    40.         NetworkInputSprint = sprint;
    41.         NetworkInputJump = jump;
    42.         NetworkInputAction = action;
    43.         NetworkInputCameraForward = camFwd;
    44.         NetworkInputCameraRight = camRght;
    45.         _lastInputTime = time;
    46.     }
    47.  
    48.     private void InputAndServer()
    49.     {
    50.         NetworkInput(
    51.             Input.GetAxisRaw( "Vertical" ),
    52.             Input.GetAxisRaw( "Horizontal" ),
    53.             Input.GetButton( "Sprint" ),
    54.             Input.GetButtonDown( "Jump" ),
    55.             Input.GetButtonDown( "Fire1" ),
    56.             CameraTransform.forward,
    57.             CameraTransform.right
    58.         );
    59.  
    60.         if ( isServer || isLocalPlayer )
    61.         {
    62.             InputVertical = NetworkInputVertical;
    63.             InputHorizontal = NetworkInputHorizontal;
    64.             InputSprint = NetworkInputSprint;
    65.             InputJump = NetworkInputJump;
    66.             InputAction = NetworkInputAction;
    67.             CameraForward = NetworkInputCameraForward;
    68.             CameraRight = NetworkInputCameraRight;
    69.         }
    70.  
    71.         if ( isServer )
    72.         {
    73.             if ( Time.time > _lastSendTime + ServerSendInterval )
    74.             {
    75.                 RpcServerResponse( transform.position, transform.rotation, MainRigidbody.velocity, MainRigidbody.angularVelocity, Time.time );
    76.                 _lastSendTime = Time.time;
    77.             }
    78.         }
    79.  
    80.         ProcessServerResponse();
    81.     }
    82.  
    83.     private void NetworkInput( float vertical, float horizontal, bool sprint, bool jump, bool action, Vector3 camFwd, Vector3 camRght )
    84.     {
    85.         if ( isLocalPlayer )
    86.         {
    87.             NetworkInputVertical = vertical;
    88.             NetworkInputHorizontal = horizontal;
    89.             NetworkInputSprint = sprint;
    90.             NetworkInputJump = jump;
    91.             NetworkInputAction = action;
    92.             NetworkInputCameraForward = camFwd;
    93.             NetworkInputCameraRight = camRght;
    94.  
    95.             while ( NetworkInputHistory.Count > 9 ) NetworkInputHistory.RemoveAt( 0 );
    96.             NetworkInputHistory.Add( new ClientInputSnapshot( vertical, horizontal, sprint, jump, action, camFwd, camRght, Time.time ) );
    97.  
    98.             if ( !isServer )
    99.             {
    100.                 CmdSendStateToServer( vertical, horizontal, sprint, jump, action, camFwd, camRght, Time.time );
    101.             }
    102.         }
    103.     }
    104.  
    105.     [ClientRpc(channel=Channels.DefaultUnreliable)]
    106.     private void RpcServerResponse( Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity, float timestamp )
    107.     {
    108.         while ( NetworkServerResponseHistory.Count > 9 )
    109.         {
    110.             NetworkServerResponseHistory.RemoveAt( 0 );
    111.         }
    112.  
    113.         ServerResponse response = new ServerResponse( position, rotation, velocity, angularVelocity, timestamp );
    114.  
    115.         NetworkServerResponseHistory.Add( response );
    116.     }
    117.  
    118.     private void ProcessServerResponse()
    119.     {
    120.         if ( NetworkServerResponseHistory.Count < 1 ) return;
    121.  
    122.         ServerResponse response = NetworkServerResponseHistory[ NetworkServerResponseHistory.Count - 1 ];
    123.  
    124.         if ( isLocalPlayer )
    125.         {
    126.             Vector3 positionBefore = transform.position;
    127.             ClientInputSnapshot inputBefore = new ClientInputSnapshot( InputVertical, InputHorizontal, InputSprint, InputJump, InputAction, CameraForward, CameraRight, 0f );
    128.  
    129.             transform.position = response.Position;
    130.             transform.rotation = response.Rotation;
    131.  
    132.             foreach ( ClientInputSnapshot inputSnapshot in NetworkInputHistory.ToList() )
    133.             {
    134.                 if ( inputSnapshot.Timestamp <= response.Timestamp )
    135.                 {
    136.                     NetworkInputHistory.Remove( inputSnapshot );
    137.                     continue;
    138.                 }
    139.  
    140.                 InputVertical = inputSnapshot.InputVertical;
    141.                 InputHorizontal = inputSnapshot.InputHorizontal;
    142.                 InputSprint = inputSnapshot.InputSprint;
    143.                 InputJump = inputSnapshot.InputJump;
    144.                 InputAction = inputSnapshot.InputAction;
    145.                 CameraForward = inputSnapshot.CameraForward;
    146.                 CameraRight = inputSnapshot.CameraRight;
    147.  
    148.                 UpdatePlayer();
    149.                 Physics.Simulate( Time.fixedDeltaTime );
    150.             }
    151.  
    152.             Vector3 positionAfter = transform.position;
    153.  
    154.             transform.position = positionBefore;
    155.             InputVertical = inputBefore.InputVertical;
    156.             InputHorizontal = inputBefore.InputHorizontal;
    157.             InputSprint = inputBefore.InputSprint;
    158.             InputJump = inputBefore.InputJump;
    159.             InputAction = inputBefore.InputAction;
    160.             CameraForward = inputBefore.CameraForward;
    161.             CameraRight = inputBefore.CameraRight;
    162.  
    163.             if ( Vector3.Distance( transform.position, positionAfter ) > 0.15f )
    164.             {
    165.                 transform.position = Vector3.MoveTowards( transform.position, positionAfter, 10f * Time.fixedDeltaTime );
    166.             }
    167.         }
    168.  
    169.         if ( !isLocalPlayer )
    170.         {
    171.             transform.position = Vector3.Lerp( transform.position, response.Position, Time.fixedDeltaTime * NetworkPositionSmoothTime );
    172.             transform.rotation = Quaternion.Lerp( transform.rotation, response.Rotation, Time.fixedDeltaTime * NetworkRotationSmoothTime );
    173.         }
    174.     }
    175.  
    176.     private void UpdatePlayer()
    177.     {
    178.         MoveVector = ( ( InputVertical * CameraForward ) + ( InputHorizontal * CameraRight ) ).normalized;
    179.         MoveSpeedCurrent = Mathf.Lerp( MoveSpeedCurrent, ( InputSprint ? 3f : 1f ), ( 10f * Time.deltaTime ) );
    180.         MoveVector *= MoveSpeedCurrent;
    181.  
    182.         MainRigidbody.velocity = new Vector3( MoveVector.x, MainRigidbody.velocity.y, MoveVector.z );
    183.  
    184.         if ( MoveVector.magnitude > 1f ) MoveVector.Normalize();
    185.         MoveVector = transform.InverseTransformDirection( MoveVector );
    186.         _turnAmount = Mathf.Atan2( MoveVector.x, MoveVector.z );
    187.         if ( _turnAmount == Mathf.PI ) _turnAmount = 0f;
    188.         transform.Rotate( 0f, _turnAmount * 540f * Time.deltaTime, 0f );
    189.     }
    190.  
    191.     private void Update()
    192.     {
    193.         InputAndServer();
    194.  
    195.         UpdatePlayer();
    196.  
    197.         if ( isLocalPlayer )
    198.         {
    199.             Physics.Simulate( Time.fixedDeltaTime );
    200.         }
    201.     }
    202. }
    203.  
    204. [System.Serializable]
    205. public struct ClientInputSnapshot
    206. {
    207.     public float InputVertical;
    208.     public float InputHorizontal;
    209.     public bool InputSprint;
    210.     public bool InputJump;
    211.     public bool InputAction;
    212.     public Vector3 CameraForward;
    213.     public Vector3 CameraRight;
    214.     public float Timestamp;
    215.  
    216.     public ClientInputSnapshot( float vertical, float horizontal, bool sprint, bool jump, bool action, Vector3 camFwd, Vector3 camRght, float time )
    217.     {
    218.         InputVertical = vertical;
    219.         InputHorizontal = horizontal;
    220.         InputSprint = sprint;
    221.         InputJump = jump;
    222.         InputAction = action;
    223.         CameraForward = camFwd;
    224.         CameraRight = camRght;
    225.         Timestamp = time;
    226.     }
    227. }
    228.  
    229. [System.Serializable]
    230. public struct ServerResponse
    231. {
    232.     public Vector3 Position;
    233.     public Quaternion Rotation;
    234.     public Vector3 Velocity;
    235.     public Vector3 AngularVelocity;
    236.     public float Timestamp;
    237.  
    238.     public ServerResponse( Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity, float time )
    239.     {
    240.         Position = position;
    241.         Rotation = rotation;
    242.         Velocity = velocity;
    243.         AngularVelocity = angularVelocity;
    244.         Timestamp = time;
    245.     }
    246. }
    Basically I have a rigidbody character I was trying to make this work with. I was trying to follow many of the tutorials out there that everyone seems to link to. Still trying to wrap my head around the whole concept simultaneously, so it is proving more difficult for me.

    If you try this code it might not work exactly as-is since I simplified a lot of stuff in order to only post the relevant parts of the code. Sorry if it is a bit messy. :p

    This code doesn't include remote client interpolation or anything like that. Was just trying to figure out this much first.

    So I was hoping someone could let me know where my code is not correct or point me in the right direction...

    Or is what I'm trying here not even possible? Sorry ahead of time from a n00b. :p

    Thanks!
     
  2. Jick87

    Jick87

    Joined:
    Oct 21, 2015
    Posts:
    124
    Bump :)
     
  3. Stanchion

    Stanchion

    Joined:
    Sep 30, 2014
    Posts:
    269
    You may want to take a look at my sample.
     
    Jick87 likes this.
  4. Jick87

    Jick87

    Joined:
    Oct 21, 2015
    Posts:
    124
    @Stanchion Wow, that looks great. Nice work! Are there any other details about this anywhere?
     
  5. Stanchion

    Stanchion

    Joined:
    Sep 30, 2014
    Posts:
    269
  6. ep1s0de

    ep1s0de

    Joined:
    Dec 24, 2015
    Posts:
    168
    Client-Server Reconciliation demonstation (Unity, RakNet):
     
  7. Stanchion

    Stanchion

    Joined:
    Sep 30, 2014
    Posts:
    269
    Are you using physics for the player? If so more details would be interesting