I would like to write a system in the PredictionSystemGroup which only executes on the subset of Entities whose Ghost mode is set to Predicted. However, I am dynamically switching these Entities back and forth between Interpolated and Predicted during Runtime using the PredictionSwitchingQueues, so I can’t rely on whatever what set in my GhostAuthoringComponent to be valid at Runtime. I can see there is a GhostMode enum inside the Netcode package, but I can’t find any Components that I could query for it check this value? Is there even a way to check this explicitly, or should I just be relying on WithAll<Simulate>()
in my Query to find predicted ghosts?
Hey devook,
Correct. You can add [WithAll(typeof(Simulate))]
to IJobXXX
queries to filter only currently predicted ghosts. This filter excludes:
- All interpolated ghosts (which have their
Simulate
component disabled). - All predicted ghosts which should not be predicted this tick (either due to not being rolled back and resimulated - i.e. not being a part of this partial snapshot - or because the tick you’re predicting is below their
PredictionStartTick
).
See Managing latency with prediction | Netcode for Entities | 1.3.0-pre.4
& Physics | Netcode for Entities | 1.3.0-pre.4
You can also query the PredictedGhost
component explicitly to get a general query containing only currently predicted ghosts. Note: Regardless of whether you query this inside or outside the prediction loop, it’ll return all currently predicted ghosts (except for Prefab
and Disabled
entities, of course, which are auto-filtered by Entities).
Ok upon further review here, I can confirm that I definitely have Ghosts in my scene that both:
- DO NOT have a PredictedGhost component
- DO have their Simulate tag enabled
From this conversation, I believe this was supposed to be impossible, right? I’m using PredictionSwitchingQueues to move Ghosted Entities between the two modes but it seems like they are inappropriately left with their Simulate tags enabled, even when no PredictedGhost component is present. This likely means that all of my Prediction logic is running against my interpolated ghosts as well, since I was doing WithAll<Simulate>
rather than WithAll<Simulate, PredictedGhost>
. If I attempt to un-check the Simulate component from the inspector in my ClientWorld, it is immediately re-enabled (presumably by a ghost snapshot from the Server)
Edit: Also upon looking at the example from NetcodeExamples, all Sphere Entities have SImulate enabled, even those which are not currently being Predicted. So, I’m not sure what this implies for my code. Is it maybe the case that the WithAll<PredictedGhost>
is implicit for Systems in the PredictedSimulationSystemGroup
, or do I need to explicitly add that to my query to make sure I’m not doing extra work on Entities that should not need it?
All ghosts (including interpolated) gets their simulate tag disabled/enabled from NetcodeClientPredictionRateManager. And then the Predicted ghosts get their Simulate tag enabled for tick. So when you are writing systems in PredictedSimulationSystemGroup you can just check against the Simulate tag without checking against PredictedGhost component.
My understanding is that any simulation logic I run on an interpolated ghost is effectively wasted compute as it’s just going to get clobbered by server snapshots. Is that not the case?
Interpolated entities are implicitly not in queries where you use Simulate tag in systems of PredictedSimulationSystemGroup. Outside of this group you will need to query the PredictedGhost component as all entities will have Simulate tag enabled.
As I’ve already mentioned, interpolated Entities do NOT have their Simulate tag disabled. You can go into the NetCode examples yourself and observe that interpolated ghosts very much have an enabled Simulate tag. Is there some other black-boxed reason that they would not show up in a query inside the PredictedSimulationSystemGroup?
Read this again. The Rate Manager which is telling PredictedSimulationSystemGroup to run first disables all Simulate tags of all ghosts. Then when it’s done its last update it enables all Simulate tags again. Thus in inspector you will see it as Enabled, while when it queries the entities in the system it will be disabled.
What you are describing here is not “disabled/enabled,” it’s “disabled, then re-enabled.” These are different things.
That aside, thank you for the answer! So it seems like there is a black-boxed and invisible thing happening here that is not reflected in the Inspector. Presumably there is some other reason to have the Simulate tag enabled for the other system groups, although I’m not sure what that would be given that the Simulate tag seems to only be relevant in the prediction group.