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

Physics + Netcode not syncing right or something

Discussion in 'NetCode for ECS' started by Guedez, Dec 24, 2019.

  1. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    823
    I am attempting to go from the netcode sample NetCube, some changes here and there, and now I can't move my character anymore
    It stopped working when I added physics body to the character, I've already "Update Component List + Generate Code" in the prefab.

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Entities;
    3. using Unity.NetCode;
    4. using Unity.Networking.Transport;
    5. using Unity.Physics;
    6. using UnityEngine;
    7.  
    8. public struct PlayerInput : ICommandData<PlayerInput> {
    9.     public uint Tick => tick;
    10.     public uint tick;
    11.     public int horizontal;
    12.     public int vertical;
    13.  
    14.     public void Deserialize(uint tick, DataStreamReader reader, ref DataStreamReader.Context ctx) {
    15.         this.tick = tick;
    16.         horizontal = reader.ReadInt(ref ctx);
    17.         vertical = reader.ReadInt(ref ctx);
    18.     }
    19.  
    20.     public void Serialize(DataStreamWriter writer) {
    21.         writer.Write(horizontal);
    22.         writer.Write(vertical);
    23.     }
    24.  
    25.     public void Deserialize(uint tick, DataStreamReader reader, ref DataStreamReader.Context ctx, PlayerInput baseline,
    26.         NetworkCompressionModel compressionModel) {
    27.         Deserialize(tick, reader, ref ctx);
    28.     }
    29.  
    30.     public void Serialize(DataStreamWriter writer, PlayerInput baseline, NetworkCompressionModel compressionModel) {
    31.         Serialize(writer);
    32.     }
    33. }
    34.  
    35. public class PlayerSendCommandSystem : CommandSendSystem<PlayerInput> { }
    36. public class PlayerReceiveCommandSystem : CommandReceiveSystem<PlayerInput> { }
    37.  
    38. [UpdateInGroup(typeof(ClientSimulationSystemGroup))]
    39. public class SamplePlayerInput : ComponentSystem {
    40.     protected override void OnCreate() {
    41.         RequireSingletonForUpdate<NetworkIdComponent>();
    42.         RequireSingletonForUpdate<EnableDOTSMMOGhostReceiveSystemComponent>();
    43.     }
    44.  
    45.     protected override void OnUpdate() {
    46.         var localInput = GetSingleton<CommandTargetComponent>().targetEntity;
    47.         if (localInput == Entity.Null) {
    48.             var localPlayerId = GetSingleton<NetworkIdComponent>().Value;
    49.             Entities.WithNone<PlayerInput>().ForEach((Entity ent, ref PlayerIDComponent player) => {
    50.                 if (player.PlayerId == localPlayerId) {
    51.                     PostUpdateCommands.AddBuffer<PlayerInput>(ent);
    52.                     PostUpdateCommands.SetComponent(GetSingletonEntity<CommandTargetComponent>(), new CommandTargetComponent { targetEntity = ent });
    53.                 }
    54.             });
    55.             return;
    56.         }
    57.         var input = default(PlayerInput);
    58.         input.tick = World.GetExistingSystem<ClientSimulationSystemGroup>().ServerTick;
    59.         if (Input.GetKey("a"))
    60.             input.horizontal -= 1;
    61.         if (Input.GetKey("d"))
    62.             input.horizontal += 1;
    63.         if (Input.GetKey("s"))
    64.             input.vertical -= 1;
    65.         if (Input.GetKey("w"))
    66.             input.vertical += 1;
    67.         var inputBuffer = EntityManager.GetBuffer<PlayerInput>(localInput);
    68.         inputBuffer.AddCommandData(input);
    69.     }
    70. }
    71.  
    72. [BurstCompile]
    73. [UpdateInGroup(typeof(GhostPredictionSystemGroup))]
    74. public class MovePlayerSystem : JobComponentSystem {
    75.     protected override Unity.Jobs.JobHandle OnUpdate(Unity.Jobs.JobHandle handle) {
    76.         handle.Complete();
    77.         var group = World.GetExistingSystem<GhostPredictionSystemGroup>();
    78.         var tick = group.PredictingTick;
    79.         var deltaTime = Time.DeltaTime;
    80.         Entities.ForEach((DynamicBuffer<PlayerInput> inputBuffer, ref PhysicsVelocity vel, ref PlayerAcceleration acc, ref PlayerMaxSpeed speed, ref PredictedGhostComponent prediction) => {
    81.             if (!GhostPredictionSystemGroup.ShouldPredict(tick, prediction)) {
    82.                 Debug.Log(World.Name + " did not predict");
    83.                 return;
    84.             }
    85.             PlayerInput input;
    86.             inputBuffer.GetDataAtTick(tick, out input);
    87.             if (input.horizontal > 0)
    88.                 vel.Linear.x = Mathf.Clamp(vel.Linear.x + deltaTime * acc.Acceleration, -speed.MaxSpeed, speed.MaxSpeed);
    89.             else if (input.horizontal < 0)
    90.                 vel.Linear.x = Mathf.Clamp(vel.Linear.x - deltaTime * acc.Acceleration, -speed.MaxSpeed, speed.MaxSpeed);
    91.             if (input.vertical > 0)
    92.                 vel.Linear.z = Mathf.Clamp(vel.Linear.z + deltaTime * acc.Acceleration, -speed.MaxSpeed, speed.MaxSpeed);
    93.             else if (input.vertical < 0)
    94.                 vel.Linear.z = Mathf.Clamp(vel.Linear.z - deltaTime * acc.Acceleration, -speed.MaxSpeed, speed.MaxSpeed);
    95.             Debug.Log(World.Name + " did predict: " + input.horizontal + ", " + input.vertical + vel.Linear);
    96.         }).WithoutBurst().Run();// (handle);
    97.         return default;
    98.     }
    99. }
    100.  
    Last 8 lines of the console, for some reason the console shows 4 servers then 4 clients then repeats rather than 1 client 1 server repeat
    Code (CSharp):
    1. ServerWorld did predict: 1, 1float3(0.1666656f, -1.8441E-06f, 0.1666667f)
    2. ServerWorld did predict: 1, 1float3(0.1666675f, -1.68932E-06f, 0.1666666f)
    3. ServerWorld did predict: 1, 1float3(0.1666656f, -1.842527E-06f, 0.1666667f)
    4. ServerWorld did predict: 1, 1float3(0.1666675f, 2.041573E-06f, 0.1666666f)
    5. ClientWorld0 did predict: 1, 1float3(5f, 1.57506f, 5f)
    6. ClientWorld0 did predict: 1, 1float3(5f, 1.57506f, 5f)
    7. ClientWorld0 did predict: 1, 1float3(5f, 1.57506f, 5f)
    8. ClientWorld0 did predict: 1, 1float3(5f, 1.57506f, 5f)
    The Project: https://www.mediafire.com/file/7ll2s2dz12nvf9s/Untituled_DOTS_MMO.zip/file
     
    Last edited: Dec 24, 2019
  2. PrisedRabbit

    PrisedRabbit

    Joined:
    Aug 14, 2012
    Posts:
    62
    Same here. How to move rigidbodies with netcode?
     
  3. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    220
    Make sure that the physics body and collider components are enabled, they're disabled in the sample project.
    I quickly tested it using the following code and it works as expected.
    Code (CSharp):
    1. [UpdateInGroup(typeof(GhostPredictionSystemGroup))]
    2. public class MoveCubeSystem : ComponentSystem
    3. {
    4.     protected override void OnUpdate()
    5.     {
    6.         var group = World.GetExistingSystem<GhostPredictionSystemGroup>();
    7.         var tick = group.PredictingTick;
    8.         var deltaTime = Time.DeltaTime;
    9.         Entities.ForEach((DynamicBuffer<CubeInput> inputBuffer, ref PhysicsVelocity vel, ref PredictedGhostComponent prediction) =>
    10.         {
    11.             if (!GhostPredictionSystemGroup.ShouldPredict(tick, prediction))
    12.                 return;
    13.             CubeInput input;
    14.             inputBuffer.GetDataAtTick(tick, out input);
    15.             vel.Linear.x = input.horizontal;
    16.             vel.Linear.z = input.vertical;
    17.         });
    18.     }
    19. }
     
  4. PrisedRabbit

    PrisedRabbit

    Joined:
    Aug 14, 2012
    Posts:
    62
    It works in sample project. But if I copy NetCube code to my empty project (or write from scratch), the cube does't move, until I remove Physics Body. Am I miss something?
     
  5. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    220
    It turned out that you need an extra system to manually update the translation.
    The system was hidden in the Asteroids sample.
    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Jobs;
    3. using Unity.NetCode;
    4. using Unity.Transforms;
    5.  
    6. namespace Asteroids.Server
    7. {
    8.     [UpdateInGroup(typeof(ServerSimulationSystemGroup))]
    9.     [UpdateBefore(typeof(GhostSimulationSystemGroup))]
    10.     public class UpdateConnectionPositionSystem : JobComponentSystem
    11.     {
    12.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    13.         {
    14.             var translationFromEntity = GetComponentDataFromEntity<Translation>(true);
    15.             return Entities.WithNativeDisableContainerSafetyRestriction(translationFromEntity).ForEach(
    16.                 (ref GhostConnectionPosition conPos, in CommandTargetComponent target) =>
    17.                 {
    18.                     if (!translationFromEntity.Exists(target.targetEntity))
    19.                         return;
    20.                     conPos = new GhostConnectionPosition
    21.                     {
    22.                         Position = translationFromEntity[target.targetEntity].Value
    23.                     };
    24.                 }).Schedule(inputDeps);
    25.         }
    26.     }
    27. }
    Logically you would need to update the rotation too if necessary.
     
  6. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Running physics on the client for ghosts is currently not supported.
    Running physics simulation on a interpolated object makes not sense since it would just do a bad prediction for one frame based on the received state.
    Running physics simulation as part of the prediction would mean that the physics systems would have to run for a select entity inside the prediction group, which is not possible at the moment. Running physics after the prediction is not the right thing to do, it would be similar to running physics for interpolated objects.

    If you just want to run physics on the server and have it replicated to the client you have to add a PhysicsBody and make sure to uncheck Predicted client and interpolated client for the PhysicsDamping, PhysicsMass and PhysicsVelocity so the physics simulation is run on the server only.

    There is also a problem with physics and netcode not knowing about each other which can mess up the ordering of the systems. You can ensure correct ordering by adding something like this
    Code (CSharp):
    1.     [UpdateBefore(typeof(BuildPhysicsWorld))]
    2.     [UpdateAfter(typeof(GhostSimulationSystemGroup))]
    3.     public class PhysicsNetCodeOrderingSystem : JobComponentSystem
    4.     {
    5.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    6.         {
    7.             return inputDeps;
    8.         }
    9.     }
    10.  
    We are investigating ways to make that easier.

    We will look closer at using physics in prediction later, for now our recommendation is to use a raycast based character controller for prediction - that is what we do in DotsSample.

    This system has nothing to do with physics, this is copying the player position to the connection entity so the position can be used for distance based priority - nothing else. Adding more systems will also affect the ordering of systems, so if it fixed anything it is likely just because it reordered the systems to something that happens to work.
     
  7. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    220
    Strangely it was the only system I had to keep to make it work, anyway thanks for clearing that up.
     
  8. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    220
    So should we still run the move system in the GhostPredictionSystemGroup then, even if it's not really predicted due to using server-side physics?

    What about other systems that affect the physics velocity, like wind or any kind of force that should be applied after the move system. In which system group are they supposed to run?
     
    T-Zee likes this.
  9. Samsle

    Samsle

    Joined:
    Mar 31, 2020
    Posts:
    103
    Does it mean this feature will come in future or should we not expect something like this?
    E.g. running the RaycastCar Demo with netcode and of course client prediction?
    There, for the car we do a lot of physic changes, apply impulses etc., if I try to apply an impulse right now to a ghost with prediction with 1sec delay, it will behave very strange.
     
    Last edited: Aug 7, 2020
  10. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    It is something we want to support and we have been experimenting a bit, but I do not have any ETA on when that will be available.
     
  11. Occuros

    Occuros

    Joined:
    Sep 4, 2018
    Posts:
    284
    Is the plan to fully support physics prediction and rollback on the client?

    Meaning to be able to have a fully physics-based environment (with joints, collisions etc.) which would work with netcode?

    (if so that would be fantastic news)
     
  12. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    We want to make the full physics simulation work in prediction, but it will have additional constraints and limitations.
    For example I don't know what would happen if you have physics on both predicted and interpolated objects, but I would expect that it is either not supported or one set is treated as kinematic or ignored when the other is updating. I do not expect that we will automatically ghost the joints from the server to the clients, at least not in all cases (join between ghost and non-ghost entity).
     
  13. NovaEiz

    NovaEiz

    Joined:
    Sep 6, 2017
    Posts:
    53


    The "Predicted client and interpolated client" checkboxes are not removed.
    For no 1 component, they are simply not removed.
    What should I do about it?

    Unity 2021.1.0f1.
    NetCode 0.6.

    Obviously, you won't be releasing a fixed version because of this.
    But can you throw off the corrected script so that I can replace it in the package?
    Please! Just checkboxes.
     
  14. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    I don't understand the question. What are you trying to do and how is it not working?
     
  15. MakotoHomma

    MakotoHomma

    Joined:
    Jun 30, 2020
    Posts:
    3
    I think this is probably the case. In Netcode 0.3 and higher, the Ghost Component Inspector only shows how ghosts are organized in code, so you can't change that checkbox manually.

    I needed to set `[GhostComponent (PrefabType = GhostPrefabType.Server)]` in PhysicsMass, PhysicsVelocity, and PhysicsDamping to get physics working in Netcode. As a result, it looks like the image.

    However, this method directly rewrites the source code of Unity Physics, and I would like you to support this setting by default if possible. Is it possible?
     

    Attached Files:

    Lontis likes this.
  16. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    The overrides per ghost prefab are partially restored so it is possible to override some things per prefab again - I think that's in 0.6

    Yes, see https://docs.unity3d.com/Packages/c...host-snapshots.html#ghost-authoring-component specifically the last paragraph:

    As well as adding attributes, you can specify rules for components which you do not have source access to by creating an assembly with a name ending with .NetCodeGen. This assembly should contain a class implementing the interface IGhostDefaultOverridesModifier. Implement the method public void Modify(Dictionary<string, GhostAuthoringComponentEditor.GhostComponent> overrides) and add an entry to the dictionary with the full name of the component as key and a value containing the desired override attributes.
     
  17. MakotoHomma

    MakotoHomma

    Joined:
    Jun 30, 2020
    Posts:
    3
  18. tylo

    tylo

    Joined:
    Dec 7, 2009
    Posts:
    154
    Does Netcode support physics in prediction now?
     
  19. Occuros

    Occuros

    Joined:
    Sep 4, 2018
    Posts:
    284
    Yes
     
    toomasio and tylo like this.