Search Unity

[U2018.3b9] PhysicsScene.Simulate() cost, multiplayer networking

Discussion in 'Physics' started by Tinus, Nov 12, 2018.

  1. Tinus

    Tinus

    Joined:
    Apr 6, 2009
    Posts:
    437
    I just saw the blog post on the new physics engine features introduced, most importantly the ability to have multiple physics scenes with full control over ticking their simulation. Really cool!

    I'm trying it out like so:

    Code (CSharp):
    1.  
    2.     using Unity.Collections;
    3.     using UnityEngine;
    4.     using UnityEngine.SceneManagement;
    5.     using Rng = Unity.Mathematics.Random;
    6.  
    7.     public class PhysicsWorldsTest : MonoBehaviour {
    8.     private Scene _offlineScene;
    9.     private PhysicsScene _offlinePhysicsScene;
    10.     private Rigidbody _offlineBody;
    11.  
    12.     private NativeArray<Vector3> _history;
    13.  
    14.     private const int TICKS = 128;
    15.  
    16.     private void Awake() {
    17.         Physics.autoSimulation = false;
    18.         Physics.autoSyncTransforms = false;
    19.  
    20.         _history = new NativeArray<Vector3>(TICKS, Allocator.Persistent);
    21.  
    22.         SetupOfflineSimulation();
    23.         SimulateOffline();
    24.     }
    25.  
    26.     private void OnDestroy() {
    27.         _history.Dispose();
    28.     }
    29.  
    30.     private void SetupOfflineSimulation() {
    31.         _offlineScene = SceneManager.CreateScene("PhysicsOffline");
    32.         _offlinePhysicsScene = _offlineScene.GetPhysicsScene();
    33.  
    34.         var obj = new GameObject("PhysicsObject");
    35.         var bod = obj.AddComponent<Rigidbody>();
    36.         _offlineBody = bod;
    37.  
    38.         SceneManager.MoveGameObjectToScene(obj, _offlineScene);
    39.         Debug.Log("Is there an object in the physics scene? " + !_offlinePhysicsScene.IsEmpty());
    40.     }
    41.  
    42.     private void SimulateOffline() {
    43.         Rng rng = new Rng(11 + (uint)Time.frameCount);
    44.  
    45.         _offlineBody.position = -1f + 2f * rng.NextFloat3();
    46.         _offlineBody.velocity = Vector3.zero;
    47.         _offlineBody.rotation = Quaternion.identity;
    48.  
    49.         for (int i = 0; i < _history.Length; i++) {
    50.             var impulse = -1f + 2f * rng.NextFloat3();
    51.             impulse.y = Mathf.Abs(impulse.y);
    52.             _offlineBody.AddForce(impulse, ForceMode.Impulse);
    53.  
    54.             _offlinePhysicsScene.Simulate(Time.fixedDeltaTime);
    55.             _history[i] = _offlineBody.position;
    56.         }
    57.     }
    58.  
    59.     void Update() {
    60.         if (Input.GetKeyDown(KeyCode.Space)) {
    61.             SimulateOffline();
    62.         }
    63.     }
    64.  
    65.     private void OnDrawGizmos() {
    66.         Gizmos.color = Color.white;
    67.  
    68.         for (int i = 0; i < _history.Length-1; i++) {
    69.             Gizmos.DrawLine(_history[i], _history[i+1]);
    70.             Gizmos.DrawSphere(_history[i], 0.05f);
    71.         }
    72.     }
    73. }
    And it works! Except, every time I call SimulateOffline() it takes 15-20ms to execute. Now, 128 ticks of physics is not nothing, but this is just a single rigidbody being pushed around.

    I'd implement multiplayer prediction/correction using this offline simulation process, since the api now contains everything I need (I think). For it to be practical though, I need to be able to do this kind of thing without breaking too much of a computational sweat.

    I'm guessing that I missed something in the setup, you know, enable a thing here, disable a thing there. Anyone have an idea?
     
    Last edited: Nov 12, 2018
    Claytonious, Singtaa and hippocoder like this.
  2. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Claytonious likes this.
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    As Anthony said, your Unity scene is using the Physics.defaultPhysicsScene because you didn't ask for a local one. You can see this because you'll find that your "_offlinePhysicsScene" is the same as the default one i.e. "_offlinePhysicsScene == Physics.defaultPhysicsScene"
     
    Claytonious likes this.
  4. Tinus

    Tinus

    Joined:
    Apr 6, 2009
    Posts:
    437
    Thanks Yant & MelvMay, I missed that.

    Modified my code like so:

    Code (CSharp):
    1.  
    2. ...
    3. var sceneParams = new CreateSceneParameters(LocalPhysicsMode.Physics3D);
    4. _offlineScene = SceneManager.CreateScene("PhysicsOffline", sceneParams);
    5. ...
    6.  
    The physics scene is now indeed different from the default. However, the resulting performance is the same.

    I did check the following:

    Code (CSharp):
    1.  
    2. Debug.Log("Is there an object in the physics scene? " + !_offlinePhysicsScene.IsEmpty());
    3. Debug.Log("Is the PhysicsScene valid? " + !_offlinePhysicsScene.IsValid());
    4. Debug.Log("Is the Scene valid? " + !_offlineScene.IsValid());
    5.  
    The run-time created Scene and PhysicsScene are apparently invalid. This happens regardless of whether I pass in the custom scene creation parameters or not. I don't know if this flag matters much in practice, it's just odd.


     
    Last edited: Nov 13, 2018
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    You're using "!_offlinePhysicsScene.IsValid()" so NOT IsValid.

    Btw, "!_offlineScene.IsValid()" isn't to do with physics, that's always been there.
     
  6. Tinus

    Tinus

    Joined:
    Apr 6, 2009
    Posts:
    437
    Whoops! That's entirely my bad.
     
  7. SpindizzyGames

    SpindizzyGames

    Joined:
    Jun 29, 2017
    Posts:
    108
    Did this solution work? can Multiple Physics Scenes be used for multiplayer prediction/correction or does it eat up too many frames?
     
  8. HexGrimm

    HexGrimm

    Joined:
    Mar 17, 2014
    Posts:
    2
    Hi
    Maybe it's too late to answer, but yes. I used it in a mobile shooter with fair prediction and server lag compensation. Everything works even on all mobile platforms. We had a game server as Unity linux build. You can play and check "Dino Squad, online PvP".
     
    SpindizzyGames likes this.
  9. SpindizzyGames

    SpindizzyGames

    Joined:
    Jun 29, 2017
    Posts:
    108
    How is the performance with this solution? How many players per server were you able to handle? Also, does it handle cross platform multiplayer ?
     
  10. allencook200

    allencook200

    Joined:
    Oct 2, 2020
    Posts:
    178
    I'm also interested in exactly this. Would love to know more about your journey creating prediction and client reconciliation using multiple physics scenes & the performance of all of it because it's exactly what I'm after, and will definitely help other people in the future, since there's literally no information about doing this in unity online.
     
    Last edited: Jan 16, 2021