Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

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

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

  1. Tinus

    Tinus

    Joined:
    Apr 6, 2009
    Posts:
    434
    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, Creepgin and hippocoder like this.
  2. yant

    yant

    Unity Technologies

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

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    1,959
    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:
    434
    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:
    1,959
    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:
    434
    Whoops! That's entirely my bad.