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

Question 1.0.0-pre.47: Simulate tag breaks entity queries for Owner Predicted ghosts of other clients

Discussion in 'NetCode for ECS' started by Richay, Mar 3, 2023.

  1. Richay

    Richay

    Joined:
    Aug 5, 2013
    Posts:
    75
    I'm finally at a point in my project where clients can connect to a host and start a game. After loading the game scene, the host spawns a hero ghost entity for each client. Each ghost has a GhostOwnerComponent set to their NetworkId, and a CommandTargetComponent on their connection entity set to the hero.

    However, while the host has all client ghosts, the clients can only see their own owned ghosts. All unowned ghosts are replicated on both clients as expected.

    Is there something I've missed? Due to a bug in pre.47 I can't check the GhostAuthoringInspectorComponent, but I rolled back my project to pre.15 and there's nothing obvious there, nor in the documentation.

    Also strangely, I tried setting the GhostOwnerComponent.NetworkId to -1 (as stated in the docs). While this didn't fix the problem, it had a bizarre side-effect: an EntityQuery on the client to get the hero always returned an empty array, even though in the entity inspector it showed the query as matching the entity and that the system had a RequireForUpdate(query) set.
     
  2. NikiWalker

    NikiWalker

    Unity Technologies

    Joined:
    May 18, 2021
    Posts:
    224
    Hey Richay! Just to rule out some obvious things:
    • Are you using relevancy at all? Temporarily disable it, if so.
    • Have you confirmed it as a replication issue? I.e. Is there any chance hero entities are being replicated, but rendering is failing, or their LocalTransform is wildly wrong? Please confirm via the Components window, with a component that only exists on the Hero entity.
      Note you will see multiple entities with that component due to prefabs being created for ghosts.
    • Presumably there are no error logs associated with this?
    • Can you open the Multiplayer > NetDbg Window and check that your client is receiving multiple of this hero entity in a single snapshot? Note that if you only see 1 hero replicated per client, it may not indicate an issue.
    • Can you set the hero to a super high importance?
    • Can you confirm that the server both:
      • Has multiple hero ghost entities.
      • Correctly receives and handles inputs from your ICommandData/IInputComponentData attached to those hero units.
    • Can you confirm that you do not remove any queried hero components on interpolated ghosts? I.e. Check the GhostComponentAttribute settings for your components.
    As always, a repro bug report project is the best way for us to diagnose this.

    Does your EntityQuery have a WithAll<GhostOwnerIsLocal>?

    EDIT2: I'll also add that I/we haven't seen this bug before. Very unexpected!

    Cheers!
     
    Last edited: Mar 3, 2023
  3. Richay

    Richay

    Joined:
    Aug 5, 2013
    Posts:
    75
    Ah oops, I completely missed that the other client ghosts are created, but they were never processed in my "new unit" system because of the EntityQuery bug.

    I've narrowed it down to enableable components being in the query.

    Before, with entities matching in the inspector but not in query.ToEntityArray():

    Code (CSharp):
    1. _newUnitQuery = new EntityQueryBuilder(Allocator.Temp)
    2.     .WithAll<Simulate, IsNewThisFrame, UnitDataECS, LocalTransform>()
    3.     .Build(this);
    After:

    Code (CSharp):
    1. _newUnitQuery = new EntityQueryBuilder(Allocator.Temp)
    2.     .WithAll<UnitDataECS, LocalTransform>()
    3.     .WithNone<TestTest>()
    4.     .Build(this);
    Having Simulate and/or IsNewThisFrame (both enableable) causes the owned ghosts to never be returned from the query.

    This only occurs with owned ghosts - all other ghost entities are matched and processed by the system, so I presume this is on the Netcode side and not Entities? Are you guys intercepting queries somehow?
     
  4. Richay

    Richay

    Joined:
    Aug 5, 2013
    Posts:
    75
    Update: it's only the Simulate tag which causes the EntityQuery issue. Keeping the IsNewThisFrame enableable component is fine.
     
  5. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    774
    I would probably add a WithAll<GhostComponent> to restrict to replicated entities.

    Also, the Simulate component is not just for the owned.
    It is used for all predicted ghost when they can be simulated. Interpolated entities (not owned) has always the Simulate tag disabled.
     
  6. Richay

    Richay

    Joined:
    Aug 5, 2013
    Posts:
    75
    So:
    - The client's heroes are set to Owner Predicted in the GhostAuthoringComponent
    - The entity inspector shows that they have Simulate enabled
    - The system inspector shows that the other clients' heroes are matched by the _newUnitQuery
    - The system uses RequireForUpdate(_newUnitQuery)

    But:
    - The system runs its OnUpdate loop, and
    - The _newUnitQuery.ToEntityArray() returns 0 items, unless the Simulate tag is removed

    I'm not sure what's happening here but I feel like it's a Netcode bug.
     
  7. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    774
    It is not a bug. As I already said. The Simulate tag is only set to enable for
    - Owner predicted ghost
    - Predicted ghost

    so other players heroes on the client are Interpolated Ghosts (because they are Onwer-Predicted). That imply the Simulate tag is false and so the query don't report them.

    And to further clarify, the Simulate tag is enable ONLY when the ghost is supposed to be simulated for that current simulated tick.

    Outside the prediction loop (before and after) the Simulate flag is enable.
    When a system run inside the PredictedSimulationSystemGroup, the simulate tag is enable only when the entity is supposed to be simulated. That it, for every simution tick, we enable/disable the flag as necessary.

    If you system need to look at all entities (not only at the predicted ones) then you don't need to check for the Simulate tag
     
    NikiWalker likes this.
  8. Richay

    Richay

    Joined:
    Aug 5, 2013
    Posts:
    75
    As I see, I understand this now. For feedback I'd say it's not clear why Simulate broke other Owned Predicted ghosts, nor is it clear from the documentation.

    I think also that my EntityQuery weirdness is because of the enableable component - afaik (now) enableable components aren't checked as part of the query within RequireForUpdate, only when getting data from the query.

    Many thanks for the info!
     
    CMarastoni likes this.