Search Unity

  1. The 2022.1 beta is now available for testing. To find out what's new, have a look at our 2022.1 beta blog post.
    Dismiss Notice

DOTS Multiplayer discussion

Discussion in 'DOTS NetCode' started by PhilSA, Jun 14, 2019.

Thread Status:
Not open for further replies.
  1. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    If your ghost consists of multiple entities they will be sent together. If you manually group ghosts together at runtime they will be sent as separate entities. Netcode is not looking at parent / child / linkedEntityGroup.
    There is also a new feature for ghost groups which allows two separate ghosts to always be sent together.

    When the scene is loaded it automatically triggers loading of all subscenes it contains into all worlds. If you manually create the worlds you need to do so before you load the scene with your content or they will not stream in any sub-scenes. It would also be possible to manually trigger subscene streaming - but in this case it would mean you need to manually keep track of all subscenes.
     
    adammpolak likes this.
  2. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    The delta compression compresses unchanged components to almost nothing (usually < 1 bit). The problem is that we still have to send the ghost id to say nothing changed - which is much larger than than the actual content. The static optimization mode is there to prevent us from sending the ghost id when nothing at all has changed.
    There is no need for a flag per component, we can optimize that without additional hints - but we can optimize differently if we know that the entire ghost is probably not changing - by using less aggressive delta compression so we can skip sending the ghost id.
     
    MarcelArioli likes this.
  3. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    26
    Thank you for your answer !
    I think I understand. But just for clarification, an example :

    I have Units (they move in 20% of the time and have ghost components like health that changes often) -> dynamic send mode

    and I have Items (multiple per unit possible, they are their own ghosts, but they are only needed for data, their position is irrelevant, they only appear on UI, also their values rarely change) -> static send mode ?
     
  4. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    Yes, I would also recommend checking size per frame in `Multiplayer > Open NetDbg` if you are not sure which is better for a given type.
     
    MarcelArioli likes this.
  5. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    155
    @timjohansson
    my frames per seconds is 200 +.
    I still have these prediction errors. To prove this I made video. Also you QA was unwilling to pass this bug forward claiming you don't support openvr when clearly this is not an openvr issue.
     
  6. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    @timjohansson just want to double check what you would suggest as a workflow for a predicted-client only component (like a camera)
    - server spawns player prefab
    - client checks for predicted component
    - client instantiates a prefab and adds it as a child its the player prefab

    Code (CSharp):
    1.         var playerEntity = GetSingletonEntity<NetworkIdComponent>();
    2.         var commandTargetFromEntity = GetComponentDataFromEntity<CommandTargetComponent>(false);
    3.         var commandBuffer = m_BeginSimEcb.CreateCommandBuffer().AsParallelWriter();
    4.         var childFromEntity = GetBufferFromEntity<Child>();
    5.         Entities
    6.             .WithoutBurst()
    7.             .WithNone<GhostPlayerState>()
    8.             .WithAll<PlayerTag, PredictedGhostComponent>()
    9.             .WithNativeDisableParallelForRestriction(commandTargetFromEntity)
    10.             .ForEach((Entity entity, int entityInQueryIndex) =>
    11.             {
    12.             var state = commandTargetFromEntity[playerEntity];
    13.             state.targetEntity = entity;
    14.             commandTargetFromEntity[playerEntity] = state;
    15.             commandBuffer.AddComponent(entityInQueryIndex, entity, new GhostPlayerState());
    16.          
    17.             //Is this how I can add a camera to a predicted-client prefab?
    18.             var camera = commandBuffer.Instantiate(cameraPrefab);
    19.             var children = childFromEntity[entity];
    20.             children.Add(camera);
    21.         }).ScheduleParallel();
    Or did I mis-interpret?

    I receive this error: "Argument 1: cannot convert from 'Unity.Entities.Entity' to 'Unity.Transforms.Child'"
     
    Last edited: Dec 8, 2020
  7. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    That looks like what I mean.

    You need to be careful with that Instantiate though, it will return not return the actual entity.
    I think you're supposed to add the Parent and LocalToParent components to the camera in this case rather than manipulating the child array though - which does not require you to store a reference to the camera entity. I haven't used parent/child in a while so not 100% sure that is the latest version.
     
    adammpolak likes this.
  8. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    Hmm, I have not seen this issue without having low performance on the server so that seems like something else. Is this client and server in the same process or are they separate instances?
     
  9. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    155
    This is the getting started example. Its default settings basically, so yea client server. I imported steamVr from asset store. I made a thread about it long time a go.
    https://forum.unity.com/threads/unity-dots-netcode-getting-started-issues.1007990/#post-6600757
     
  10. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    26
    I have two more general questions regarding conversion and netcode :
    ConvertToClientServerEntity is deprecated > use Subscene workflow instead.

    - What is the intended workflow for hybrids that cannot be in a subscene ? (because for example they have a reference to a scriptable object, there are other reasons too IMO)

    - What if I only want to load a specific subscene on server OR client ? (I don't see such a setting, is it intended to write that manually by reading scripting define UNITY_SERVER for example and don't auto load subscene ?)

    Bonus question : How to load a subscene the intended way when disabling auto load :)
     
  11. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    155
    I was wondering this too.

    came up with this horrible solution!
    Code (CSharp):
    1.  
    2.             serverStart = World.DefaultGameObjectInjectionWorld.GetExistingSystem<GameInitConnection>();
    3.             serverStart.MultiPlayerGameStarted = true;
    4.             serverStart.Update();
    5.             server = ServerWorld.GetExistingSystem<GoInGameServerSystem>();
    6.             server.MultiPlayerGameStarted = true;
    7.             server.Update();
    8.             client = ClientWorld.GetOrCreateSystem<GoInGameClientSystem>();
    9.             client.MultiPlayerGameStarted = true;
    10.             client.Update();
    11.  
    12.             GetComponent<LoadNetCodeSystemAndSubScene>().NetWorkScene.gameObject.GetComponent<SubScene>().enabled =  true;
    What I think is horrible about this is that I'm manually building, updating and managing the ecs systems. Bonus points for easy reading and easy usage.
     
    Last edited: Dec 9, 2020
    florianhanke likes this.
  12. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    @11marcello11 I had similar questions, check out this post and the following ones. I think they answer most of your questions
    https://forum.unity.com/threads/generate-sub-scenes-programmatically.868984/#post-6598072
     
    MarcelArioli likes this.
  13. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    26
    thanks for the link, didn't spot that :)

    It answers the concrete implementation question, but it leaves the questions :

    - Is this really intended ? (Seems just to error prone to write a manual component like that, why not have a ClientServerSubscene provided by unity ? )

    - What's with conversion outside of a subscene ? Is it really intended to NOT have any conversion outside of subscenes anymore ?
     
    adammpolak likes this.
  14. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    26
    I think it would be a really good time to have updated and detailed information about what the new conversion workflow should look like when using Unity NetCode.
    (I humbly appologize if such a thing exists, in that case i didn't find it easy enough, the netcode documentation package doesn't address this)

    It seems odd to browse several forums, discord servers and documentation pages to gather basic informations.

    I really like pages like
    https://docs.unity3d.com/Packages/com.unity.tiny@0.16/manual/intro-for-unity-developers.html
    https://docs.unity3d.com/Packages/com.unity.entities@0.16/manual/conversion.html

    would be awesome to find more informations about conversion workflow (with and without netcode involved) there :)
     
    Lionious likes this.
  15. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    26
    In case anyone needs this too : Simple ClientServerSubscene that will only load if server or client world exists

    Code (CSharp):
    1.  /// <summary>
    2.   /// Helps loading a subscene only on server or client.
    3.   /// This is basically ConvertToClientServerEntity code.
    4.   /// </summary>
    5.   [DisallowMultipleComponent]
    6.   [RequireComponent(typeof(SubScene))]
    7.   public class ClientServerSubscene : MonoBehaviour
    8.   {
    9.     [Flags]
    10.     public enum ConversionTargetType
    11.     {
    12.       None = 0x0,
    13.       Client = 0x1,
    14.       Server = 0x2,
    15.       ClientAndServer = 0x3
    16.     }
    17.  
    18.     [SerializeField] public ConversionTargetType ConversionTarget = ConversionTargetType.ClientAndServer;
    19.  
    20.     private void Reset()
    21.     {
    22.       //we only want to load with TryLoad(), not automatic.
    23.       GetComponent<SubScene>().AutoLoadScene = false;
    24.     }
    25.  
    26.     void Start()
    27.     {
    28.       TryLoad();
    29.     }
    30.  
    31.     public void TryLoad()
    32.     {
    33.       foreach (var world in World.All)
    34.       {
    35.         bool convertToClient = world.GetExistingSystem<ClientSimulationSystemGroup>() != null;
    36.         bool convertToServer = world.GetExistingSystem<ServerSimulationSystemGroup>() != null;
    37.  
    38.         convertToClient &= (ConversionTarget & ConversionTargetType.Client) != 0;
    39.         convertToServer &= (ConversionTarget & ConversionTargetType.Server) != 0;
    40.  
    41.         if
    42.         (
    43.           convertToClient ||
    44.           convertToServer
    45.         )
    46.         {
    47.           var sceneSystem = world.GetExistingSystem<SceneSystem>();
    48.           sceneSystem.LoadSceneAsync(GetComponent<SubScene>().SceneGUID);
    49.         }
    50.       }
    51.     }
    52.   }
     
    adammpolak, florianhanke and bb8_1 like this.
  16. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    86
    If I remember correctly the rpc codegen supports fixed strings
     
    adammpolak likes this.
  17. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    @timjohansson is it possible to create an entity in the client/server world directly from a Monobehaviour?

    I override bootstrap to create client and server worlds with:
    Code (CSharp):
    1. ClientServerBootstrap.CreateServerWorld(world, "ServerWorld");
    2. ClientServerBootstrap.CreateClientWorld(world, "ClientWorld");
    On start up the system that listens on a port "ServerConnectionControl" is limited to TargetWorld.Server:
    Code (CSharp):
    1. [UpdateInWorld(UpdateInWorld.TargetWorld.Server)]
    2. public class ServerConnectionControl : SystemBase

    Is there a similar way to create a Entity from a Monobehaviour into the server world?

    var ServerDataEntity = World.Server.EntityManager.CreateEntity();
    returns

    'World' does not contain a definition for 'Server'


    Currently I have to: if(word in worlds.all) has ClientSimulationSystemGroup each time I need to be specifically in the client world.
     
    Last edited: Dec 23, 2020
    florianhanke likes this.
  18. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    26
    @timjohansson

    I have yet another question that might be hard to answer :)

    The situation :
    - 100 ghosts (units)
    of which following components are ghostcomponents
    - health
    - mana
    - weaponstate
    - animationstate
    and around 10-15 additional components which only exist on server (like armor, speed, resistance, range, etc.)

    but here comes the thing : I wrote a small AI with ECS (very simple state machine) that adds
    components to those ghosts like DoAttack, DoMove, DoRangeCheck and so on (there are 12 different AI 'nodes').

    This means that usually the chunks change quite a bit because of those AI components on the unit ghosts, do you see a problem with that ? (and in generall, is it a problem to have that many components on a ghost that are not ghostcomponents ?)

    Below i attached a fatal error that occurs when i instantiate 24 unit-ghosts in a job. The system reporting the issue is random (in this case it was my CalcPlayerTargetUnitsServerSystem, but sometimes its the GhostUpdateSystem).
    I was wondering wether that issue has something to do with my setup described above.

    NullReferenceException: Object reference not set to an instance of an object
    Unity.Entities.ArchetypeChunk.GetNativeArray (Unity.Entities.EntityTypeHandle entityTypeHandle) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ArchetypeChunkArray.cs:220)
    Unity.Entities.ChunkIterationUtility._GatherEntities (Unity.Entities.Entity* entities, Unity.Entities.EntityQuery& entityQuery, Unity.Entities.EntityTypeHandle& entityTypeHandle) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ChunkIterationUtility.cs:258)
    Unity.Entities.ChunkIterationUtility._mono_to_burst_GatherEntities (System.IntPtr entities, Unity.Entities.EntityQuery& entityQuery, Unity.Entities.EntityTypeHandle& entityTypeHandle) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ChunkIterationUtility.interop.gen.cs:193)
    Unity.Entities.ChunkIterationUtility._forward_mono_GatherEntities (Unity.Entities.Entity* entities, Unity.Entities.EntityQuery& entityQuery, Unity.Entities.EntityTypeHandle& entityTypeHandle) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ChunkIterationUtility.interop.gen.cs:199)
    Unity.Entities.ChunkIterationUtility.GatherEntities (Unity.Entities.Entity* entities, Unity.Entities.EntityQuery& entityQuery, Unity.Entities.EntityTypeHandle& entityTypeHandle) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ChunkIterationUtility.interop.gen.cs:180)
    Unity.Entities.ChunkIterationUtility.CreateEntityArray (Unity.Entities.UnsafeMatchingArchetypePtrList matchingArchetypes, Unity.Collections.Allocator allocator, Unity.Entities.EntityTypeHandle typeHandle, Unity.Entities.EntityQuery entityQuery, System.Int32 entityCount) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ChunkIterationUtility.cs:284)
    Unity.Entities.EntityQueryImpl.ToEntityArray (Unity.Collections.Allocator allocator, Unity.Entities.EntityQuery outer) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/EntityQuery.cs:490)
    Unity.Entities.EntityQuery.ToEntityArray (Unity.Collections.Allocator allocator) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/EntityQuery.cs:1283)
    FFE.Combat.CalcPlayerTargetUnitsServerSystem.OnUpdate () (at Assets/Scripts/Combat/Runtime/Systems/ServerOnly/CalcPlayerTargetUnitsServerSystem.cs:31)
    Unity.Entities.SystemBase.Update () (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/SystemBase.cs:413)
    Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:435)
    UnityEngine.Debug:LogException(Exception)
    Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Stubs/Unity/Debug.cs:19)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:440)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:387)
    Unity.NetCode.ServerSimulationSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.netcode@0.5.0-preview.5/Runtime/ClientServerWorld/ServerSimulationSystemGroup.cs:72)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:435)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:387)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:435)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:387)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
    Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ScriptBehaviourUpdateOrder.cs:333)

    NullReferenceException: Object reference not set to an instance of an object
    Unity.Entities.ChunkDataUtility.GetIndexInTypeArray (Unity.Entities.Archetype* archetype, System.Int32 typeIndex) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ChunkDataUtility.cs:65)
    Unity.Entities.ArchetypeChunk.GetChangeVersion[T] (Unity.Entities.ComponentTypeHandle`1[T] chunkComponentTypeHandle) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ArchetypeChunkArray.cs:396)
    Unity.Entities.ArchetypeChunk.DidChange[T] (Unity.Entities.ComponentTypeHandle`1[T] chunkComponentTypeHandle, System.UInt32 version) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Iterators/ArchetypeChunkArray.cs:258)
    Unity.Transforms.LocalToParentSystem+UpdateHierarchy.Execute (Unity.Entities.ArchetypeChunk chunk, System.Int32 index, System.Int32 entityOffset) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Transforms/LocalToParentSystem.cs:60)
    Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].ExecuteInternal (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/IJobChunk.cs:370)
    Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].Execute (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/IJobChunk.cs:337)
    Unity.Jobs.JobHandle:ScheduleBatchedJobsAndComplete(JobHandle&)
    Unity.Jobs.JobHandle:Complete()
    Unity.Entities.ComponentDependencyManager:CompleteAllJobsAndInvalidateArrays() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentDependencyManager.cs:129)
    Unity.Entities.EntityDataAccess:BeforeStructuralChange() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/EntityDataAccess.cs:285)
    Unity.Entities.EntityCommandBuffer:StartTrackingChanges(EntityDataAccess*, UnsafeList*, ArchetypeChanges&) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/EntityCommandBuffer.cs:2127)
    Unity.Entities.EntityCommandBuffer:playbackInternal(EntityDataAccess*) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/EntityCommandBuffer.cs:1411)
    Unity.Entities.EntityCommandBuffer:playback(EntityManager) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/EntityCommandBuffer.cs:1369)
    Unity.Entities.EntityCommandBufferSystem:FlushPendingBuffers(Boolean) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/EntityCommandBufferSystem.cs:225)
    Unity.Entities.EntityCommandBufferSystem:OnUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/EntityCommandBufferSystem.cs:190)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:435)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:387)
    Unity.NetCode.ServerSimulationSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.netcode@0.5.0-preview.5/Runtime/ClientServerWorld/ServerSimulationSystemGroup.cs:72)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:435)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:387)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:435)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystemGroup.cs:387)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
    Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ScriptBehaviourUpdateOrder.cs:333)
     
    adammpolak likes this.
  19. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    FYI anyone else that is getting "jittering" when changing PhysicsVelocity

    After fiddling with NetCode + Physics for a quite a while I learned that you should not put your system that responds to commands in: [UpdateInGroup(typeof(GhostPredictionSystemGroup))] even though it seems like you should.

    You would think you should, but it is only used for the predicting tick. If you try to put your input response system in here you will get all sorts of issues.

    It is better to bail and not use PhysicsVelocity.Linear at all in your project if you are using NetCode + Physics

    You can create a VelocityComponent
    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.NetCode;
    4.  
    5. // [GhostComponent(PrefabType = GhostPrefabType.AllPredicted, OwnerPredictedSendType = GhostSendType.Predicted)]
    6. [GenerateAuthoringComponent]
    7. public struct VelocityComponent : IComponentData
    8. {
    9.     [GhostField]
    10.     public float3 Linear;
    11. }
    12.  
    And a MovementSystem
    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.Transforms;
    4. using UnityEngine;
    5. using Unity.Burst;
    6. using Unity.NetCode;
    7.  
    8. [UpdateInWorld(UpdateInWorld.TargetWorld.ClientAndServer)]
    9. [UpdateInGroup(typeof(GhostPredictionSystemGroup))]
    10. public class MovementSystem : SystemBase
    11. {
    12.     private GhostPredictionSystemGroup m_PredictionGroup;
    13.  
    14.     protected override void OnCreate()
    15.     {
    16.         m_PredictionGroup = World.GetOrCreateSystem<GhostPredictionSystemGroup>();
    17.     }
    18.  
    19.     protected override void OnUpdate()
    20.     {
    21.         var deltaTime = m_PredictionGroup.Time.DeltaTime;
    22.         var currentTick = m_PredictionGroup.PredictingTick;
    23.  
    24.         Entities
    25.         .ForEach((ref Translation position, in VelocityComponent velocity, in PredictedGhostComponent prediction) =>
    26.         {
    27.             if (!GhostPredictionSystemGroup.ShouldPredict(currentTick, prediction))
    28.                 return;
    29.  
    30.             position.Value.xyz += velocity.Linear * deltaTime;
    31.            
    32.         }).ScheduleParallel();
    33.     }
    34. }

    The collisions won't be perfect but its better than unusable movement
     
    Last edited: Jan 9, 2021
    bb8_1 likes this.
  20. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    There is nothing builtin apart from looping over the worlds and finding the correct one. Since you said earlier in the post that you manually create the worlds you could just store them in a public static when creating them and use that from the monobehaviour though.
     
    adammpolak likes this.
  21. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    I don't think that should be a big problem. You can loose history and get slightly larger snapshots if you have frequent structural changes on the server, and having too large entities on the server means fewer entities per chunk which can affect performance slightly. Neither of those should be significant though.

    Hard to say for sure what is causing that. The second stacktrace being a ECB playback reminds me a little bit of a bug we found recently which could be triggered by GhostDistancePartitioningSystem in some rare cases - so you can try disabling distance paritioning if you are using it.
     
  22. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    26
    @timjohansson
    Thanks for your insights :)

    FYI : I filed a unity bug report a week ago, i got rid of those errors by reverting entities 0.16 to 0.14 and netcode 0.5 to 0.4.

    Edit : will try upgrading packages and disabling distance partitioning and test it as soon as I have time, thanks for the hint
     
    Last edited: Jan 11, 2021
  23. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    Correct, using physics simulation in the prediction is not currently supported. The prediction group does not include physics simulation, so if you need to roll back 10 frames what will happen is not that you set the velocity and run physics 10 times, you will set velocity 10 times and run physics once after the prediction loop is done.
    It is ok to use raycasts in the prediction though - you could use that to make the movement slightly better until physics sim in prediction lands (but I don't know what that will be)
     
  24. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    Super helpful thank you @timjohansson

    Is there anyway to adjust PhysicsVelocity with DOTS Physics + NetCode?

    I am currently using my own VelocityComponent and MovementSystem but it makes for not great collisions with Physics Shapes.

    How can I "add thrust" to an object (increase the PhysicsVelocity.Linear) without the "stuttering"?



    Currently when I try to update PhysicsVelocity.Linear it gets "jittery" and I have pinpointed it to the PhysicsVelocity.Linear randomly decreasing and then going back to normal

    upload_2021-1-11_11-53-34.png

    (using Physics.Extensions linear impulses didn't work either)
     
  25. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    1,072
    When physics sim in prediction feature will land? Soon or still long time to go?
     
  26. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    Are you talking about predicted or interpolated ghosts?

    For interpolated ghosts you should set them as kinematic on the client side and only use physics velocity / simulation on the server. The positions will be updated on the client based on the simulation running on the server. If you also run the simulation on the client you will get incorrect results since that would make them some strange hybrid of interpolated / predicted - and they would be almost guaranteed to jitter.

    For predicted ghosts that is what we don't support yet and it is a lot of work to add. You'd need to move the physics systems into the prediction group, ghost the velocity component so it can roll back and use ShouldPredict to temporarily mark objects as kinematic - or something like that. I don't really know all the details of how to do it and probably will not until we implement it - at which point physics in prediction will be supported.
    The most common workaround is to write your own controller for kinematic objects based on raycasts (that's sort of what the dots sample does for characters)
     
    bb8_1 likes this.
  27. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    Sorry for being unclear @timjohansson .

    I meant I have a predicted-player object (the capsule in the video). I want to increase its PhysicsVelocity.Linear (or the appropriate equivalent) when I hit "W" on my keyboard. So which ever way it is facing, it will accelerate in that direction.

    Currently I store a "thrust == 1" ICommandData and I play it back in my InputResponseSystem (which is run on both the client and server similar to the "SteeringSystem" in the Asteroids sample.

    How do I have the client "predict" that the player will thrust forward and also have the server also increase the PhysicsVelocity.Linear? (if that is appropriate).

    Currently I have added a VelocityComponent to the player entity and created a MovementSystem that changes the position of the entity based on VelocityComponent.Linear * deltaTime. I assume this is not the way to do it because it "teleports" the entity by changing the position so it "merges" with asteroids instead of bouncing off of them.

    Have I missed something involving Kinematics?

    Note, this is what I mean by wanting to update physics velocity on user input:

    Code (CSharp):
    1.         Entities
    2.         .WithReadOnly(inputFromEntity)
    3.         .WithAll<PlayerTag, PlayerCommand, Child>()
    4.         .ForEach((Entity entity, int nativeThreadIndex, ref Rotation rotation, ref PlayerStateComponent state, ref VelocityComponent velocityComponent,
    5.                 in GhostOwnerComponent ghostOwner, in PredictedGhostComponent prediction) =>
    6.         {
    7.  
    8.             if (!GhostPredictionSystemGroup.ShouldPredict(currentTick, prediction))
    9.                 return;
    10.             var input = inputFromEntity[entity];
    11.  
    12.             PlayerCommand inputData;
    13.             if (!input.GetDataAtTick(currentTick, out inputData))
    14.                 inputData.shoot = 0;
    15.  
    16.             state.State = inputData.thrust;
    17.  
    18.             if (inputData.right == 1)
    19.             {   //thrust to the right of where the player is facing
    20.                 velocityComponent.Linear += math.mul(rotation.Value, new float3(1,0,0)).xyz * playerForce * deltaTime;
    21.                 // PhysicsComponentExtensions.ApplyLinearImpulse(ref physicsVelocity, physicsMass, (math.mul(rotation.Value, new float3(1,0,0)).xyz));
    22.                
    23.             }
    24.             if (inputData.left == 1)
    25.             {   //thrust to the left of where the player is facing
    26.                 velocityComponent.Linear += math.mul(rotation.Value, new float3(-1,0,0)).xyz * playerForce * deltaTime;
    27.                 // PhysicsComponentExtensions.ApplyLinearImpulse(ref physicsVelocity, physicsMass, (math.mul(rotation.Value, new float3(-1,0,0)).xyz));
    28.             }
    29.             if (inputData.thrust == 1)
    30.             {   //thrust forward of where the player is facing
    31.                 velocityComponent.Linear += math.mul(rotation.Value, new float3(0,0,1)).xyz * playerForce * deltaTime;
    32.                 // PhysicsComponentExtensions.ApplyLinearImpulse(ref physicsVelocity, physicsMass, (math.mul(rotation.Value, new float3(0,0,1)).xyz));
    33.             }
    34.             if (inputData.reverseThrust == 1)
    35.             {   //thrust backwards of where the player is facing
    36.                 velocityComponent.Linear += math.mul(rotation.Value, new float3(0,0,-1)).xyz * playerForce * deltaTime;
    37.                 // PhysicsComponentExtensions.ApplyLinearImpulse(ref physicsVelocity, physicsMass, (math.mul(rotation.Value, new float3(0,0,-1)).xyz));
    38.             }
     
    Last edited: Jan 11, 2021
  28. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    1,072
    Hi @timjohansson, current I found that Entities.WithChangeFilter<SomeComponent>() will not work as expected i.e. only run once when SomeComponent data changes when SomeComponent data marked as GhostField. Is there any plan to improve it? Is there any good solution to workaround it that make it only update once when SomeComponent data changes with its data marked as GhostField?
     
  29. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    1,072
    Hi @timjohansson, any plan to make GhostComponent attribute working on child entity too? For example u add [GhostComponent(PrefabType = GhostPrefabType.Server)] attribute to ComponentA that is belongs to child entity, ComponentA will only exists at server.
     
  30. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    We don't have any short term plans to improve that, but we probably investigate it more carefully at some point in the future.

    Some of the GhostComponent parameters will be supported on child entities in the next netcode release, I think PrefabType is one of the supported properties.
     
    bb8_1 and optimise like this.
  31. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    @timjohansson sorry to double ping, but is there any "approved" (recommended?) way to get immediate feedback on the predicted-client when you would like to update the PhysicsVelocity?
     
  32. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    There is unfortunately no recommended solution for using physics simulation (with PhysicsVelocity) in client side prediction yet. The recommendation right now is to use a kinematic character controller based on raycasts for prediction. We do want to support physics simulation in prediction in the future, but i do not know when that will be available.
     
    bb8_1 and adammpolak like this.
  33. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    Thank you!
     
  34. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    What processes take place if I put a "NetworkStreamRequestDisconnect" on the Network Connection Entity (NCE) on the client side?

    I am guessing this deletes the NCE on the server side?
    Or does it just add NetworkStreamDisconnected on the NCE on the server side?

    Edit: It adds NetworkStreamDisconnected on the other side THEN deletes it.
     
    Last edited: Jan 22, 2021
  35. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    1,072
    Hi @steveeHavok. Can you provide a kinematic character controller based on raycasts for prediction sample into dots physics repo? I need it for this netcode.
     
    adammpolak likes this.
  36. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    86
    adammpolak likes this.
  37. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    1,072
    What I want is raycast based character controller. This sample is normal character controller.
     
  38. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    86
    The controller I linked does use collider casts and can be used just fine in prediction.
    What is a normal character controller?
     
  39. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    1,072
    Hi @timjohansson.
    1) Currently I need a feature that able to choose which subscene to be included into client, another subscene into server and yet another subscene into both client and server. I just need to choose the option at Subscene monobehavior to do that. Another feature I needed is there is subscene I want to make available at both client and server but I strip out something at Server. For current use case I want to strip RenderMesh also means strip out art asset from real build but still preserve physics collider. It's very similar feature like untick RenderMesh at GhostComponent monobehavior. But still when enter playmode at Editor I still able to load all the subscenes regardless of whether it belongs to client and/or server with client and server worlds to do testing easily. Then when I roll out the real build the build pipeline will dynamically figure out the only assets like art assets need to be included into the build.

    2) Does this feature coming soon? Actually what I think this feature needs to combine with loading art assets on demand meaning that it will only start loading its 3D Model, texture, material etc when spawning ghost if it has art assets. The prefab inside GhostCollection is just lightweight version without art asset loaded yet. I believe this problem will need Dots Addressables to solve it.
     
    Last edited: Jan 21, 2021
  40. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    Does adding a "NetworkStreamRequestDisconnect" work both ways?

    If I put one on the server would all clients receive it?

    Also, if the server times out from the clients, do clients receive a "NetworkStreamDisconnected" component on their NCEs?

    EDIT: IT DOES
     
    Last edited: Jan 22, 2021
  41. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    677
    Thanks for NetCode 0.6!

    I'm trying rewriting some systems to ISystemBase but I don't know how to solve for getting ticks to the job.
    ISystemBase doesn't seem to have a reference to its World, so I can't get the GhostPredictionSystemGroup.
    What am I missing or is this not supported?
     
  42. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    86
    NetCode 0.6 sadly doesn't support ISystemBase. The systems won't be created and as you mentioned the tick information is not accessible from unmanaged systems.
     
  43. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    NetCode 0.6, rocks thank you NetCode team!

    @timjohansson Questions from Change log:

    "Added support for extrapolation when the tick being applied to interpolated ghosts on the client has not been received yet and is outside the interpolation delay. Set the new Smoothing field in the GhostField attribute to SmoothingAction.InterpolateAndExtrapolate to enable extrapolation."

    How can this be done for a Physics Shape/Body?

    If a client is receiving interpolated snapshots of a Physics Shape/Body, how do we set SmoothingAction.interpolateAndExtrapolate?
     
    Last edited: Jan 24, 2021
  44. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    The only way to do that right now is to uncheck Auto load and load the subscenes manually. We do want to make that easier but it is not something we are working on right now.

    You can convert a subscene in different ways for client and server, you need to assign the guid of the build configuration with NetCodeConversionSettings to World.GetOrCreateSystem<SceneSystem>().BuildConfigurationGUID at runtime to make it load the correct version of the subscene.
    To remove the meshes on the server you would need to write a conversion system which removes the meshes if the NetCodeConversionSettings conversion target is server. This is what the GhostAuthoringComponent does so you can look at that in the package cache for an example.

    In 0.6 you do not need to use the ghost collection, the prefabs are picked up automatically. It still does not make it easy to load the prefabs on demand on the client and we are not working on that right now so not sure when that will land.
    We are not planning to change how assets for prefabs is loaded right now either, you'd have to remove hte assets from the prefab and load them manually to make something like that work at the moment.
     
    adammpolak and optimise like this.
  45. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    Interpolated ghosts do not run the physics simulation on the client, so you set extrapolation on the the Translation and Rotation components (it is enabled by default) and it will extrapolate them. There is currently no way to use the physics data for extrapolation - it is just based on the components themselves.
     
    adammpolak likes this.
  46. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    Nice that it is by default, thank you!
     
  47. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    @timjohansson apologies for such a rudimentary question so late in the game but I realized there is a huge gap in my knowledge of how to create ghosted entities because all of my ghosted entities so far have been a prefab with a GhostAuthoringComponent.

    If I am running in ServerSimulationSystemGroup and I want to create a ghosted entity for some reason:

    var highScore = EntityManager.CreateEntity();
    EntityManager.AddComponent<HighestScoreComponent>(highScore);

    Where HighestScoreComponent
    Code (CSharp):
    1. using Unity.Networking.Transport;
    2. using Unity.NetCode;
    3. using Unity.Burst;
    4. using Unity.Entities;
    5. using Unity.Collections;
    6.  
    7. [GhostComponent]
    8. public struct HighestScoreComponent : IComponentData
    9. {
    10.     [GhostField]
    11.     public FixedString64 playerName;
    12.  
    13.     [GhostField]
    14.     public int highestScore;
    15. }
    Is not working. Is adding a GhostComponent decorator to a IComponentData not enough to make the parent entity ghosted?

    I am trying to figure out how to follow what happens with "GhostAuthoringComponent" in the package code but I am getting a bit lost.

    It seems like in order to make a Ghost it should be a Prefab with a GhostAuthoringComponent otherwise the conversion won't take place?
     
    Last edited: Jan 25, 2021
  48. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    402
    All ghosts need to have an entity prefab, and that prefab must exist on both client and server. Without having that the client does not know what to spawn when it receives the ghost since we never send the list of components over the network (and that list might not be the same on the client and server).
    We generate some meta data in the prefab from the GhostAuthoringComponent during conversion which makes it tricky to create the entity prefabs from code at runtime, so having a converted prefab asset for it is by far the easiest. We have talked about making it easier to create entity prefabs for ghosts at runtime - but it is not something we are working on right now.
    The easiest way to get a prefab asset to spawn at runtime is to have a singleton in a converted subscene which has something like this:
    Code (CSharp):
    1. [GenerateAuthoringComponent]
    2. public struct Spawner : IComponentData
    3. {
    4.     public Entity Something;
    5. }
    Then you can spawn it at runtime by doing something like this:
    Code (CSharp):
    1. var prefab = GetSingleton<Spawner>().Something;
    2. EntityManager.Instantiate(prefab);
     
    Lukas_Kastern and bb8_1 like this.
  49. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    397
    Much appreciated! Makes sense, it isn't a big deal at all to always use a prefab to make ghosts so I get the non-priority.
     
  50. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    1,072
    1)
    @timjohansson Does this solution able to strip the related art assets (Models, Textures, materials, shaders, animations etc) when rolling out server build so I can get very small build size?

    2) Currently even the latest Netcode 0.6, the performance is very slow at Editor even Editor Release Mode is selected. When enter play mode I get super flow fps if u use laptop that has very weak CPU compares to desktop PC. From task manager, I see the CPU utilization is quite low. Maybe the bottleneck is main thread and Editor not able to fully utilize multithreading. Is there any plan to improve that? I think if I do even complex simulation I will get single digit fps.

    upload_2021-1-28_20-45-36.png
     
    Last edited: Jan 28, 2021
Thread Status:
Not open for further replies.
unityunity