Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Question How to setup distance-based importance scale?

Discussion in 'NetCode for ECS' started by YuriyVotintsev, Dec 10, 2022.

  1. YuriyVotintsev

    YuriyVotintsev

    Joined:
    Jun 11, 2013
    Posts:
    93
    I have really heavy ghosts (~350 bytes uncompressed, or ~400bits after quantization and compression). With default snapshot size and without importance scale ~30 ghosts can be updated by network ~3 times per second (NetworkTickRate=30). I'm trying to setup distance-based importance scale so that nearest 1-2 ghosts updates every tick, and farthest ghosts can be updated once per second, or even more. But all my attempts has no effect. all ghosts updates with same interval.
    Here are my settings:
    Code (CSharp):
    1.  
    2. var scaleFunctionPointer = GhostDistanceImportance.ScaleFunctionPointer;
    3.  
    4. var grid = EntityManager.CreateEntity();
    5. EntityManager.SetName(grid, "GhostImportanceSingleton");
    6. EntityManager.AddComponentData(grid, new GhostDistanceData
    7. {
    8.     TileSize = new int3(1, 1, 1),
    9.     TileCenter = new int3(0, 0, 0),
    10.     TileBorderWidth = new float3(0.5f, 0.5f, 0.5f),
    11. });
    12. EntityManager.AddComponentData(grid, new GhostImportance
    13. {
    14.     ScaleImportanceFunction = scaleFunctionPointer,
    15.     GhostConnectionComponentType = ComponentType.ReadOnly<GhostConnectionPosition>(),
    16.     GhostImportanceDataType = ComponentType.ReadOnly<GhostDistanceData>(),
    17.     GhostImportancePerChunkDataType = ComponentType.ReadOnly<GhostDistancePartitionShared>(),
    18. });
    19.  
    20. var ghostSendSystemData = SystemAPI.GetSingleton<GhostSendSystemData>();
    21. // ........ // here i tried any combinations of GhostSendSystemData, no effect.
    22. SystemAPI.SetSingleton(ghostSendSystemData);
    23.  
    What am i doing wrong? (I tried many variants in Tile settings, but no effect
     
  2. miniwolf_unity

    miniwolf_unity

    Unity Technologies

    Joined:
    Apr 10, 2018
    Posts:
    139
    One thing that caught me off guard while testing this, you must add a GhostConnectionPosition component to each connection. If you put a breakpoint inside GhostSendSystem on the line containing:
    Code (CSharp):
    1. if (connectionHasConnectionData && ghostChunk.Has(ref ghostImportancePerChunkTypeHandle))
    If you did the same as me you will notice that connectionHasConnectionData is false.

    In my test I added this system:

    Code (CSharp):
    1. [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
    2. [BurstCompile]
    3. public partial struct UpdateConnectionPositionSystem : ISystem
    4. {
    5.     [BurstCompile]
    6.     public void OnUpdate(ref SystemState state)
    7.     {
    8.         var ecb = new EntityCommandBuffer(Allocator.Temp);
    9.         foreach (var (_, entity) in SystemAPI.Query<NetworkIdComponent>().WithNone<GhostConnectionPosition>().WithEntityAccess())
    10.         {
    11.             ecb.AddComponent(entity, new GhostConnectionPosition
    12.             {
    13.                 Position = new float3(),
    14.             });
    15.         }
    16.         ecb.Playback(state.EntityManager);
    17.     }
    18. }
    Note that here this position will always be 0,0,0. If you want this to follow your player or other target, the system would have to take that into account.

    I see it written in the documentation: https://docs.unity3d.com/Packages/c.../optimizations.html#distance-based-importance

    But the example does not make this clear. I will update this.
     
    Last edited: Dec 12, 2022
  3. YuriyVotintsev

    YuriyVotintsev

    Joined:
    Jun 11, 2013
    Posts:
    93
    Yes, It wasn't clear from documentation, but i figured out this my self from asteroids example. So problem is in something else.
     
  4. miniwolf_unity

    miniwolf_unity

    Unity Technologies

    Joined:
    Apr 10, 2018
    Posts:
    139
    We will just have to investigate, I did my own implementation where it works. And as you mention Asteroids is also utilizing this feature as well.
    It is not clear to me what and why you need to modify the GhostSendSystemData, can you elaborate on this? There should be no need to modify this data in a standard setup.
     
  5. YuriyVotintsev

    YuriyVotintsev

    Joined:
    Jun 11, 2013
    Posts:
    93
    It was suggestion by @NikiWalker in another thread to change MaxSendEntities and MinSendImportance, but it is not important because not modifying GhostSendSystemData didn't give result as well.

    I figured out that importance scale works on chunks of entities and i have only two chunks of entities. To split my 30 ghost each to separate chunk I used shared component with random value for each entitiy, just to be sure that each entity is calculated separatly (for test purposes primarily). Is this the normal approach?
     
  6. miniwolf_unity

    miniwolf_unity

    Unity Technologies

    Joined:
    Apr 10, 2018
    Posts:
    139
    It is not the normal approach to set a random value for each entity. The GhostImportancePerChunkDataType represents some shared value (for example an int3) for entities that should be grouped together (get the same importance value).

    In the asteroids sample the distance to the player is the value used. It is set by the UpdateTileIndexJob by computing the tileindex based on the distance.
    The GhostDistanceImportance.Scale function, use this Index to compute how far the tile is from the centerTile, which is defined as the GhostConnectionPosition - TileCenter(set in yours to new int3(0, 0, 0)) / TileSize (set in yours to new int3(1, 1, 1))

    By setting a random value you are essentially placing them at random distances from the center. Which does not do what you want.
     
  7. YuriyVotintsev

    YuriyVotintsev

    Joined:
    Jun 11, 2013
    Posts:
    93
    I used my own shared component to split into chunks, because i have only two chunks of entities and all that importance works only with chunks, not with single entitiy. I don't do anything random with GhostImportancePerChunkDataType.