I’ve been working with Netcode for Entities and recently encountered a potential issue. I’m unsure whether this is a bug or if I’m overlooking something fundamental.
Setup
I am spawning ghost entities that reference other ghost entities. Specifically, my setup consists of:
- Character Entity (Ghosted prefab, Interpolated, Static, Importance: 5)
- CharacterManager Entity (Ghosted prefab, Interpolated, Static, Importance: 1)
Both are separate prefabs (CharacterManager prefab is not a child of the character, the reason being that some characters will be dynamic, others static, so it is separated into a new ghost prefab to ensure the static-ness of this entity as the components inside it don’t update that often)
Each Character Entity contains a EntityManagerLink component that references its associated CharacterManager Entity:
public struct EntityManagerLink: IComponentData
{
[GhostField]
public Entity Entity; //During runtime in a baking system, I assign this to be the CharacterManager Prefab entity, I also tried a different setup, more info below
}
Entities are spawned at the start of the session in a Host configuration (server + client). The client connects only after all required prefabs are loaded.
Spawning Process
Entities are spawned in a loop as follows:
var characterPrefab = SystemAPI.GetSingleton<CharacterPrefab>();
int entitiesPerAxis = 10;
for (int x = 0; x < entitiesPerAxis; x++)
{
for (int y = 0; y < entitiesPerAxis; y++)
{
state.EntityManager.InstantiateEntity(characterPrefab, new float3(x, 0, y) / 1.5f, quaternion.identity, 1, "Character");
}
}
(Note: My InstantiateEntity is just an extension that sets position, rotation, scale, nothing special.)
Each Character Entity initially has an InitTag component, which is removed at the end of the frame. While InitTag is enabled, the corresponding CharacterManager Entity is instantiated, and the EntityManagerLink component is assigned accordingly to the Character Entity:
foreach (var (_, entityManagerLink, e) in SystemAPI.Query<EnabledRefRO<InitTag>, RefRW<EntityManagerLink>>().WithEntityAccess())
{
var characterManagerEntity = state.EntityManager.InstantiateEntity(entityManagerLink.ValueRO.Value); // Instantiate CharacterManager Entity which by default is a prefab entity
entityManagerLink.ValueRW.Value = characterManagerEntity ; // assign our instantiated EntityManagerLink Entity (GhostField)
}
Observed Issue
When spawning a small number of entities, everything works as expected. However, when spawning hundreds of entities, I notice that some EntityManagerLink components on the client remain on their default unassigned value (Entity.Null) indefinitely, while others have their EntityManagerLink field properly synced.
Upon inspecting the server side, all entities have their EntityManagerLink field properly set. I understand that GhostField data may take a few ticks to propagate to the client, but in my case, some fields never synced to the client.
Debugging Attempts
Network Debugger
No apparent bandwidth issues.
Importance Factor Adjustment:
Changing the importance of the Character Entity changes the success rate of EntityManagerLink GhostField syncing. For testing I would wait for all ghost entities to appear on the client and then look at the Network Debugging to make sure there isn’t any more data being transmitted, after which I would dump results (3 tests per importance value change, spawning 900 character entities (which would chain spawn an additional 900 CharacterManager Entities and link them via the EntityManagerLink component):
(Character Entity Importance: 1, CharacterManager Entity Importance: 1) results:
- [Client] ‘28’ unassigned
GhostFieldEntity values out of ‘900’ - [Client] ‘31’ unassigned
GhostFieldEntity values out of ‘900’ - [Client] ‘20’ unassigned
GhostFieldEntity values out of ‘900’
(Character Entity Importance: 1, CharacterManager Entity Importance: 5) results:
- [Client] ‘676’ unassigned
GhostFieldEntity out of ‘900’ - [Client] ‘765’ unassigned
GhostFieldEntity out of ‘900’ - [Client] ‘873’ unassigned
GhostFieldEntity out of ‘900’
(Character Entity Importance: 25, CharacterManager Entity Importance: 25) results:
- [Client] ‘887’ unassigned
GhostFieldEntity out of ‘900’ - [Client] ‘900’ unassigned
GhostFieldEntity out of ‘900’ - [Client] ‘900’ unassigned
GhostFieldEntity out of ‘900’
We can clearly see a pattern in the success rate of the GhostField being assigned and the importance factor. On a side note my client indeed sees all 900 ‘CharacterManager’ Entities.
Using GhostGroup
This resulted in a 100% success rate of the GhostField getting synced, however when I look in the Network Debugger, these static entities are sending continuous data every tick, also upon looking at them in the inspector, I can see the snapshot index change as if it were a dynamic entity. (in my scenario I don’t need these to sync in the same snapshot, so checking GhostGroup was just for testing sake)
Edit 1:
Built Application
I tried running two application instances, the first in host mode, wait a couple of seconds for everything to spawn, connect a second client, the same issue would still occur (on both host client and the additional client).
Edit 2:
Changing the Character Entity to be Dynamic (instead of Static)
This also resulted in a 100% success rate in the GhostField syncing
Changed EntityManagerLink component
public struct EntityManagerLink: IComponentData
{
[GhostField]
public Entity Entity;
[GhostField (SendData = false)]
public Entity Prefab;
}
This was more of a sanity check to see if anything different would happen, I would spawn the entity instance from the Prefab field instead and then assign it to the GhostField, which resulted in no change.
Questions
- What could cause some
GhostFieldentity values to never synchronize, even though they are correctly assigned on the server? - Is there a limitation with ghosted static entities that I am unaware of?
- Could this be a mapping issue, where the client receives an entity reference but doesn’t know which entity to map it to?
- Why would using ghost groups result in 100% success rate of the
GhostFieldsyncing and why do they send continuous data even if both prefabs are set to be static
Thanks in advance, and I apologize for the long post! My project is quite a bit more complex; otherwise, I would have provided a sample. I wanted to ask first in case I missed something obvious before creating one.
Any insights or suggestions would be greatly appreciated!
Curently using:
Netcode for Entities 1.4.0
Entities 1.3.9
Unity Editor version 6000.0.37f1