Search Unity

How to use GhostPredictionSystemGroup.ShouldPredict before updating an entity if using DOTS Physics?

Discussion in 'NetCode for ECS' started by adammpolak, May 30, 2022.

  1. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    From the docs:
    Client
    The basic flow on the client is:

    • NetCode applies the latest snapshot it received from the server to all predicted entities.
    • While applying the snapshots, NetCode also finds the oldest snapshot it applied to any entity.
    • Once NetCode applies the snapshots, the GhostPredictionSystemGroup runs from the oldest tick applied to any entity, to the tick the prediction is targeting.
    • When the prediction runs, the GhostPredictionSystemGroup sets the correct time for the current prediction tick in the ECS TimeData struct. It also sets GhostPredictionSystemGroup.PredictingTick to the tick being predicted.
    Because the prediction loop runs from the oldest tick applied to any entity, and some entities might already have newer data, you must check whether each entity needs to be simulated or not. To perform these checks, call the static method GhostPredictionSystemGroup.ShouldPredict before updating an entity. If it returns false the update should not run for that entity.
    I am using DOTS Physics. The translation/rotation is updated without a system of mine.

    I would like to run prediction on Asteroids (not controllable) that are using PhysicsShape and PhysicsBody near my player.

    Does NetCode automatically handle doing predictions correctly for DOTS Physics?
     
  2. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    894
    NetCode has support for predicted physics in 0.5. IIRC we already posted something about that in the forum as well.
    You need to enable the feature by creating a singleton with the PredictedPhysicsConfig component (see the documention in the class and the PredictionSwitching sample)
    Once the singleton is present, all the physics systems are moved into a new group inside the GhostPredictionSystemGroup that run in sync with the ghost simulation as expected.
    The PhysicsVelocity is replicated to all clients and it is the only thing it necessary to sync the physic state.

    Asteroids does not use any physics. The only sample that use predicted physics is the PredictionSwitching.
     
  3. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    Do the systems that respond to the ICommandData need to be in a special group?
     
  4. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    894
    I mean, depend. The only real requirements is that any system that modify the ghosts state must run in GhostPredictionSystemGroup.
    Physics systems are going to be moved in the GhostPredictedPhysicsSystemGroup.
    If you have systems that need to act on the physics data (and as such they depend PhysicWorldBuildSystem etc etc) you need to setup the after/before dependency as usual (ex: [UpdateAfter(PhysicWorldBuildSystem)]).
    You can schedule that systems in either the GhostPredictedPhysicsSystemGroup or inside the FixedStepSimulatonSystemGroup (where the physic systems originally belong).
    Because your system need to run after/before the physics systems, it will be automatically moved in the new group at runtime
     
  5. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    Got it.

    So my InputResponseSystem (in which I change the PhysicsVelocity of a Player object) runs in ClientAndServer.

    - I would assume the client "sees" the state of the game (the rendering loop)
    - then an input is ingested to create an ICommandData (from the user responding to what they see)
    - the ICommandData takes a while to get to the Server but should be immediately acted upon by by the client be cause it is predicted
    - I would assume that I would want to change the Velocity BEFORE the physics is run (so it is not like the input had no affect on the player for a frame)
    - And then build the Physics world AFTER that velocity update

    So if that is the case it would be set up as:

    Code (CSharp):
    1. [UpdateInWorld(TargetWorld.ClientAndServer)]
    2. [UpdateInGroup(typeof(PredictedPhysicsSystemGroup))]
    3. [UpdateBefore(typeof(BuildPhysicsWorld))]
    4. public partial class InputResponseMovementSystem : SystemBase
    Resulting in:
    - InputSystem running in GhostInputSystemGroup
    - InputResponseMovementSystem running just before BuildPhysicsWorld
    upload_2022-6-5_13-15-4.png

    Does that work or would this cause unexpected behavior I am not aware of?
     
  6. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    894
    It should work exactly has you expect.