While implementing the PredictedSpawning feature in at test project to learn and gain experiences using ECS netcode I looked into the Netcode sample “PredictedSpawning”:
There I found a small issue in the struct “ClassificationSystem” regarding the “GhostCollectionPrefab” which contains all the ghost prefabs. The prefab supplied by the “GrenadeSpawner” authoring could not find a match in the stated collection. Therefore the line 14 of the OnUpdate-call got never executed which can be identified setting a breakpoint there which is never reached while playing the scene in the editor:
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
if (m_GhostType == 0)
{
// Lookup the grenade prefab entity in the ghost prefab list, from there we can find the ghost type for this prefab
var prefabEntity = SystemAPI.GetSingleton<GrenadeSpawner>().Grenade;
var collectionEntity = SystemAPI.GetSingletonEntity<GhostCollection>();
var ghostPrefabTypes = state.EntityManager.GetBuffer<GhostCollectionPrefab>(collectionEntity);
for (int i = 0; i < ghostPrefabTypes.Length; ++i)
{
if (ghostPrefabTypes[i].GhostPrefab == prefabEntity)
m_GhostType = ghostPrefabTypes[i].GhostType.GetHashCode();
}
}
m_SnapshotDataLookupHelper.Update(ref state);
m_PredictedGhostSpawnLookup.Update(ref state);
m_GrenadeDataLookup.Update(ref state);
var ghostCollection = SystemAPI.GetSingletonEntity<GhostCollection>();
var classificationJob = new ClassificationJob
{
ghostMap = SystemAPI.GetSingleton<SpawnedGhostEntityMap>().Value,
snapshotDataLookupHelper = m_SnapshotDataLookupHelper,
ghostCollectionSingleton = ghostCollection,
spawnListEntity = SystemAPI.GetSingletonEntity<PredictedGhostSpawnList>(),
PredictedSpawnListLookup = m_PredictedGhostSpawnLookup,
grenadeDataLookup = m_GrenadeDataLookup,
ghostType = m_GhostType
};
state.Dependency = classificationJob.Schedule(state.Dependency);
}
The code in the stuct “ClassificationJob” which depends on the “GhostType” may not work properly then. I only wanted to report the issue. The sample still works despite the issue. I tested with Unity 2022.2.14 and used the samples provided for version 1.0.0-pre.65 of ECS.
Thanks for reporting. Indeed is not correct, since the prefab that is registered with the GhostCollection is not the one in the spawner.
The ghostType is used only for avoiding a classification issue with predicted players. So it does not cause problem for the local player in general.
But indeed this should be fixed! Thanks!
1 Like
@CMarastoni
So, the samples have been updated with release of Unity 2022.3, so I checked the PredictedSpawn sample again. Line 14 of my intial post is indeed executed now, so the m_ghostType is set and provided to the classification job. But lets have a look at the Execute method of the ClassificationJob:
public void Execute(DynamicBuffer<GhostSpawnBuffer> ghosts, DynamicBuffer<SnapshotDataBuffer> data)
{
var predictedSpawnList = PredictedSpawnListLookup[spawnListEntity];
var snapshotDataLookup = snapshotDataLookupHelper.CreateSnapshotBufferLookup();
for (int i = 0; i < ghosts.Length; ++i)
{
var newGhostSpawn = ghosts[i];
if (newGhostSpawn.SpawnType != GhostSpawnBuffer.Type.Predicted || newGhostSpawn.HasClassifiedPredictedSpawn || newGhostSpawn.PredictedSpawnEntity != Entity.Null)
continue;
// Mark all the grenade spawns as classified even if not our own predicted spawns
// otherwise spawns from other players might be picked up by the default classification system when
// it runs when we happen to have a predicted spawn in the predictedSpawnList not yet classified here
if (newGhostSpawn.GhostType == ghostType)
newGhostSpawn.HasClassifiedPredictedSpawn = true;
// Find new ghost spawns (from ghost snapshot) which match the predict spawned ghost type handled by
// this classification system. Match the spawn ID data from the new spawn (by lookup it up in
// snapshot data) with the spawn IDs of ghosts in the predicted spawn list. When matched we replace
// the ghost entity of that new spawn with our predict spawned entity (so the spawn will not result
// in a new instantiation).
for (int j = 0; j < predictedSpawnList.Length; ++j)
{
if (newGhostSpawn.GhostType == predictedSpawnList[j].ghostType)
{
if (snapshotDataLookup.TryGetComponentDataFromSnapshotHistory(newGhostSpawn.GhostType, data, out GrenadeData grenadeData, i))
{
var spawnIdFromList = grenadeDataLookup[predictedSpawnList[j].entity].SpawnId;
if (grenadeData.SpawnId == spawnIdFromList)
{
newGhostSpawn.PredictedSpawnEntity = predictedSpawnList[j].entity;
predictedSpawnList[j] = predictedSpawnList[predictedSpawnList.Length - 1];
predictedSpawnList.RemoveAt(predictedSpawnList.Length - 1);
break;
}
}
}
}
ghosts[i] = newGhostSpawn;
}
}
I tested with launching a grenade and the line 15 in the Execute method above gets not called which uses the ghostType. You may correct me, but the ghostType member of the job contains a hashcode and the hashcode does not seem to match the newGhostSpawn.GhostType. The number ranges seem to be quite different. Thats what it looks in the Debugger when launching a grenade:
So it seems to me, that there is still a bug. I use a GhostClassificationSystem in my project which is based on the sample code and only want to ensure that it works as expected.
Edit: Created a bug report in IN-45105
The bug report for IN-45105 was confirmed two months ago, but unfortunately the stated issue tracker link is no more valid:
Can the devs please tell whats the status here.
Hey FaithlessOne! You’re right, it’s very odd that the ECSB-504 issue no longer exists, but the IN-45105 link does. I’ve pinged the relevant QA folk to see what’s going on there. As for status: We’re actually looking at this issue in this sprint, so it should be sorted relatively soon. Thanks for the report about the bug link itself (lol), and for your patience.
1 Like
Please see this forum thread for the quick fix: Classification ghost type in samples seems wrong
1 Like