Exemple #1
0
        protected override void OnCreate()
        {
            m_GhostPredictionSystemGroup   = World.GetExistingSystem <GhostPredictionSystemGroup>();
            m_GhostPredictionHistorySystem = World.GetExistingSystem <GhostPredictionHistorySystem>();
            m_GhostCollectionSystem        = World.GetExistingSystem <GhostCollectionSystem>();

            m_PredictionQuery   = GetEntityQuery(ComponentType.ReadOnly <PredictedGhostComponent>(), ComponentType.ReadOnly <GhostComponent>());
            m_ChildEntityLookup = new NativeHashMap <Entity, EntityChunkLookup>(1024, Allocator.Persistent);
            m_ChildEntityQuery  = GetEntityQuery(ComponentType.ReadOnly <GhostChildEntityComponent>());
        }
        protected override void OnCreate()
        {
            m_GhostPredictionSystemGroup  = World.GetExistingSystem <GhostPredictionSystemGroup>();
            m_ClientSimulationSystemGroup = World.GetExistingSystem <ClientSimulationSystemGroup>();

            PredictionState            = new NativeHashMap <ArchetypeChunk, System.IntPtr>(128, Allocator.Persistent);
            m_StillUsedPredictionState = new NativeHashMap <ArchetypeChunk, int>(128, Allocator.Persistent);
            m_NewPredictionState       = new NativeQueue <PredictionStateEntry>(Allocator.Persistent);
            m_PredictionQuery          = GetEntityQuery(ComponentType.ReadOnly <PredictedGhostComponent>(), ComponentType.ReadOnly <GhostComponent>());

            m_GhostCollectionSystem = World.GetOrCreateSystem <GhostCollectionSystem>();
            m_ChildEntityLookup     = new NativeHashMap <Entity, EntityChunkLookup>(1024, Allocator.Persistent);
            m_ChildEntityQuery      = GetEntityQuery(ComponentType.ReadOnly <GhostChildEntityComponent>());
        }
Exemple #3
0
        protected override void OnCreate()
        {
            m_GhostPredictionSystemGroup   = World.GetExistingSystem <GhostPredictionSystemGroup>();
            m_GhostPredictionHistorySystem = World.GetExistingSystem <GhostPredictionHistorySystem>();

            m_PredictionQuery   = GetEntityQuery(ComponentType.ReadOnly <PredictedGhostComponent>(), ComponentType.ReadOnly <GhostComponent>());
            m_ChildEntityLookup = new NativeHashMap <Entity, EntityChunkLookup>(1024, Allocator.Persistent);
            m_ChildEntityQuery  = GetEntityQuery(ComponentType.ReadOnly <GhostChildEntityComponent>());

            m_UserSpecifiedComponentData = new NativeList <ComponentType>(8, Allocator.Persistent);
            m_SmoothingActions           = new NativeHashMap <ComponentType, SmoothingActionState>(32, Allocator.Persistent);

            RequireSingletonForUpdate <GhostCollection>();
            RequireSingletonForUpdate <SmoothingAction>();
        }
Exemple #4
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex, DynamicComponentTypeHandle *ghostChunkComponentTypesPtr, int ghostChunkComponentTypesLength)
            {
                if (!predictionState.TryGetValue(chunk, out var state) ||
                    (*(PredictionBackupState *)state).entityCapacity != chunk.Capacity)
                {
                    return;
                }

                var ghostComponents = chunk.GetNativeArray(ghostType);
                int ghostTypeId     = ghostComponents[0].ghostType;
                var typeData        = GhostTypeCollection[ghostTypeId];

                var headerSize = PredictionBackupState.GetHeaderSize();
                var entitySize = PredictionBackupState.GetEntitiesSize(chunk.Capacity, out var singleEntitySize);
                int baseOffset = typeData.FirstComponent;

                Entity *backupEntities = PredictionBackupState.GetEntities(state, headerSize);
                var     entities       = chunk.GetNativeArray(entityType);

                var predictedGhostComponents = chunk.GetNativeArray(predictedGhostType);

                byte *dataPtr           = PredictionBackupState.GetData(state, headerSize, entitySize);
                int   numBaseComponents = typeData.NumComponents - typeData.NumChildComponents;

                for (int comp = 0; comp < numBaseComponents; ++comp)
                {
                    int compIdx = GhostComponentIndex[baseOffset + comp].ComponentIndex;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                    if (compIdx >= ghostChunkComponentTypesLength)
                    {
                        throw new System.InvalidOperationException("Component index out of range");
                    }
#endif
                    if ((GhostComponentCollection[compIdx].SendMask & requiredSendMask) == 0)
                    {
                        continue;
                    }
                    var compSize = GhostComponentCollection[compIdx].ComponentSize;
                    if (chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                    {
                        var compData = (byte *)chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[compIdx], compSize).GetUnsafeReadOnlyPtr();
                        for (int ent = 0; ent < entities.Length; ++ent)
                        {
                            // If this entity did not predict anything there was no rollback and no need to debug it
                            if (!GhostPredictionSystemGroup.ShouldPredict(tick, predictedGhostComponents[ent]))
                            {
                                continue;
                            }
                            if (entities[ent] == backupEntities[ent])
                            {
                                SmoothComponent(compData + compSize * ent, dataPtr + compSize * ent, GhostComponentCollection[compIdx].ComponentType);
                            }
                        }
                    }

                    dataPtr = PredictionBackupState.GetNextData(dataPtr, compSize, chunk.Capacity);
                }
                if (typeData.NumChildComponents > 0)
                {
                    var linkedEntityGroupAccessor = chunk.GetBufferAccessor(linkedEntityGroupType);
                    for (int comp = numBaseComponents; comp < typeData.NumComponents; ++comp)
                    {
                        int compIdx = GhostComponentIndex[baseOffset + comp].ComponentIndex;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        if (compIdx >= ghostChunkComponentTypesLength)
                        {
                            throw new System.InvalidOperationException("Component index out of range");
                        }
#endif
                        if ((GhostComponentCollection[compIdx].SendMask & requiredSendMask) == 0)
                        {
                            continue;
                        }
                        var compSize  = GhostComponentCollection[compIdx].ComponentSize;
                        var entityIdx = GhostComponentIndex[baseOffset + comp].EntityIndex;

                        for (int ent = 0; ent < chunk.Count; ++ent)
                        {
                            // If this entity did not predict anything there was no rollback and no need to debug it
                            if (!GhostPredictionSystemGroup.ShouldPredict(tick, predictedGhostComponents[ent]))
                            {
                                continue;
                            }
                            if (entities[ent] != backupEntities[ent])
                            {
                                continue;
                            }
                            var linkedEntityGroup = linkedEntityGroupAccessor[ent];
                            if (childEntityLookup.TryGetValue(linkedEntityGroup[entityIdx].Value, out var childChunk) &&
                                childChunk.chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                            {
                                var compData = (byte *)childChunk.chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[compIdx], compSize).GetUnsafePtr();
                                SmoothComponent(compData + compSize * childChunk.index, dataPtr + compSize * ent, GhostComponentCollection[compIdx].ComponentType);
                            }
                        }

                        dataPtr = PredictionBackupState.GetNextData(dataPtr, compSize, chunk.Capacity);
                    }
                }
            }
Exemple #5
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex, DynamicComponentTypeHandle *ghostChunkComponentTypesPtr, int ghostChunkComponentTypesLength,
                                DynamicComponentTypeHandle *userTypes, int userTypesLength)
            {
                if (!predictionState.TryGetValue(chunk, out var state) ||
                    (*(PredictionBackupState *)state).entityCapacity != chunk.Capacity)
                {
                    return;
                }

                var GhostTypeCollection      = GhostTypeCollectionFromEntity[GhostCollectionSingleton];
                var GhostComponentIndex      = GhostComponentIndexFromEntity[GhostCollectionSingleton];
                var GhostComponentCollection = GhostComponentCollectionFromEntity[GhostCollectionSingleton];

                var ghostComponents = chunk.GetNativeArray(ghostType);

                int ghostTypeId = ghostComponents.GetFirstGhostTypeId();

                if (ghostTypeId < 0)
                {
                    return;
                }

                var typeData = GhostTypeCollection[ghostTypeId];

                var headerSize = PredictionBackupState.GetHeaderSize();
                var entitySize = PredictionBackupState.GetEntitiesSize(chunk.Capacity, out var singleEntitySize);

                Entity *backupEntities = PredictionBackupState.GetEntities(state);
                var     entities       = chunk.GetNativeArray(entityType);

                var predictedGhostComponents = chunk.GetNativeArray(predictedGhostType);

                int numBaseComponents = typeData.NumComponents - typeData.NumChildComponents;
                int baseOffset        = typeData.FirstComponent;

                var actions      = new NativeList <SmoothingActionState>(Allocator.Temp);
                var childActions = new NativeList <SmoothingActionState>(Allocator.Temp);

                int backupOffset = headerSize + entitySize;

                // todo: this loop could be cached on chunk.capacity, because now we are re-calculating it everytime.
                for (int comp = 0; comp < typeData.NumComponents; ++comp)
                {
                    int index         = baseOffset + comp;
                    int compIdx       = GhostComponentIndex[index].ComponentIndex;
                    int serializerIdx = GhostComponentIndex[index].SerializerIndex;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                    if (compIdx >= ghostChunkComponentTypesLength)
                    {
                        throw new System.InvalidOperationException("Component index out of range");
                    }
#endif
                    if ((GhostComponentIndex[index].SendMask & requiredSendMask) == 0)
                    {
                        continue;
                    }

                    if (GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                    {
                        backupOffset += PredictionBackupState.GetDataSize(GhostSystemConstants.DynamicBufferComponentSnapshotSize, chunk.Capacity);
                        continue;
                    }
                    var compSize = GhostComponentCollection[serializerIdx].ComponentSize;

                    if (smoothingActions.TryGetValue(GhostComponentCollection[serializerIdx].ComponentType,
                                                     out var action))
                    {
                        action.compIndex        = compIdx;
                        action.compSize         = compSize;
                        action.serializerIndex  = serializerIdx;
                        action.entityIndex      = GhostComponentIndex[index].EntityIndex;
                        action.compBackupOffset = backupOffset;

                        if (comp < numBaseComponents)
                        {
                            actions.Add(action);
                        }
                        else
                        {
                            childActions.Add(action);
                        }
                    }
                    backupOffset += PredictionBackupState.GetDataSize(compSize, chunk.Capacity);
                }

                foreach (var action in actions)
                {
                    if (chunk.Has(ghostChunkComponentTypesPtr[action.compIndex]))
                    {
                        for (int ent = 0; ent < entities.Length; ++ent)
                        {
                            // If this entity did not predict anything there was no rollback and no need to debug it
                            if (!GhostPredictionSystemGroup.ShouldPredict(tick, predictedGhostComponents[ent]))
                            {
                                continue;
                            }

                            if (entities[ent] != backupEntities[ent])
                            {
                                continue;
                            }

                            var compData = (byte *)chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[action.compIndex], action.compSize).GetUnsafePtr();

                            void *usrDataPtr = null;
                            if (action.userTypeId >= 0 && chunk.Has(userTypes[action.userTypeId]))
                            {
                                var usrData = (byte *)chunk.GetDynamicComponentDataArrayReinterpret <byte>(userTypes[action.userTypeId], action.userTypeSize).GetUnsafeReadOnlyPtr();
                                usrDataPtr = usrData + action.userTypeSize * ent;
                            }

                            byte *dataPtr = ((byte *)state) + action.compBackupOffset;
                            action.action.Ptr.Invoke(compData + action.compSize * ent, dataPtr + action.compSize * ent,
                                                     usrDataPtr);
                        }
                    }
                }

                var linkedEntityGroupAccessor = chunk.GetBufferAccessor(linkedEntityGroupType);
                foreach (var action in childActions)
                {
                    for (int ent = 0; ent < chunk.Count; ++ent)
                    {
                        // If this entity did not predict anything there was no rollback and no need to debug it
                        if (!GhostPredictionSystemGroup.ShouldPredict(tick, predictedGhostComponents[ent]))
                        {
                            continue;
                        }
                        if (entities[ent] != backupEntities[ent])
                        {
                            continue;
                        }
                        var linkedEntityGroup = linkedEntityGroupAccessor[ent];
                        if (childEntityLookup.TryGetValue(linkedEntityGroup[action.entityIndex].Value, out var childChunk) &&
                            childChunk.chunk.Has(ghostChunkComponentTypesPtr[action.compIndex]))
                        {
                            var compData = (byte *)childChunk.chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[action.compIndex], action.compSize).GetUnsafePtr();

                            void *usrDataPtr = null;
                            if (action.userTypeId >= 0 && chunk.Has(userTypes[action.userTypeId]))
                            {
                                var usrData = (byte *)chunk.GetDynamicComponentDataArrayReinterpret <byte>(userTypes[action.userTypeId], action.userTypeSize).GetUnsafeReadOnlyPtr();
                                usrDataPtr = usrData + action.userTypeSize * ent;
                            }

                            byte *dataPtr = ((byte *)state) + action.compBackupOffset;
                            action.action.Ptr.Invoke(compData + action.compSize * childChunk.index, dataPtr + action.compSize * ent, usrDataPtr);
                        }
                    }
                }
            }
Exemple #6
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex, DynamicComponentTypeHandle *ghostChunkComponentTypesPtr, int ghostChunkComponentTypesLength)
            {
                if (!predictionState.TryGetValue(chunk, out var state) ||
                    (*(PredictionBackupState *)state).entityCapacity != chunk.Capacity)
                {
                    return;
                }

                var GhostTypeCollection      = GhostTypeCollectionFromEntity[GhostCollectionSingleton];
                var GhostComponentIndex      = GhostComponentIndexFromEntity[GhostCollectionSingleton];
                var GhostComponentCollection = GhostComponentCollectionFromEntity[GhostCollectionSingleton];

                var ghostComponents = chunk.GetNativeArray(ghostType);
                int ghostTypeId     = ghostComponents.GetFirstGhostTypeId();

                if (ghostTypeId < 0)
                {
                    return;
                }
                var typeData   = GhostTypeCollection[ghostTypeId];
                int baseOffset = typeData.FirstComponent;

                Entity *backupEntities = PredictionBackupState.GetEntities(state);
                var     entities       = chunk.GetNativeArray(entityType);

                var predictedGhostComponents = chunk.GetNativeArray(predictedGhostType);

                byte *dataPtr           = PredictionBackupState.GetData(state);
                int   numBaseComponents = typeData.NumComponents - typeData.NumChildComponents;

                for (int comp = 0; comp < numBaseComponents; ++comp)
                {
                    int compIdx       = GhostComponentIndex[baseOffset + comp].ComponentIndex;
                    int serializerIdx = GhostComponentIndex[baseOffset + comp].SerializerIndex;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                    if (compIdx >= ghostChunkComponentTypesLength)
                    {
                        throw new System.InvalidOperationException("Component index out of range");
                    }
#endif
                    if ((GhostComponentIndex[baseOffset + comp].SendMask & requiredSendMask) == 0)
                    {
                        continue;
                    }

                    var compSize = GhostComponentCollection[serializerIdx].ComponentType.IsBuffer
                        ? GhostSystemConstants.DynamicBufferComponentSnapshotSize
                        : GhostComponentCollection[serializerIdx].ComponentSize;
                    if (chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                    {
                        if (!GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                        {
                            var compData = (byte *)chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[compIdx], compSize).GetUnsafeReadOnlyPtr();
                            for (int ent = 0; ent < entities.Length; ++ent)
                            {
                                // If this entity did not predict anything there was no rollback and no need to debug it
                                if (!GhostPredictionSystemGroup.ShouldPredict(tick, predictedGhostComponents[ent]))
                                {
                                    continue;
                                }
                                if (entities[ent] == backupEntities[ent])
                                {
                                    int errorIndex = GhostComponentIndex[baseOffset + comp].PredictionErrorBaseIndex;

                                    var errors = new UnsafeList <float>(((float *)predictionErrors.GetUnsafePtr()) + errorIndex + ThreadIndex * numPredictionErrors, numPredictionErrors - errorIndex);
                                    GhostComponentCollection[serializerIdx].ReportPredictionErrors.Ptr.Invoke((System.IntPtr)(compData + compSize * ent), (System.IntPtr)(dataPtr + compSize * ent), ref errors);
                                }
                            }
                        }
                        else
                        {
                            //FIXME Buffers need to report error for the size and an aggregate for each element in the buffer
                        }
                    }

                    dataPtr = PredictionBackupState.GetNextData(dataPtr, compSize, chunk.Capacity);
                }
                if (typeData.NumChildComponents > 0)
                {
                    var linkedEntityGroupAccessor = chunk.GetBufferAccessor(linkedEntityGroupType);
                    for (int comp = numBaseComponents; comp < typeData.NumComponents; ++comp)
                    {
                        int compIdx       = GhostComponentIndex[baseOffset + comp].ComponentIndex;
                        int serializerIdx = GhostComponentIndex[baseOffset + comp].SerializerIndex;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        if (compIdx >= ghostChunkComponentTypesLength)
                        {
                            throw new System.InvalidOperationException("Component index out of range");
                        }
#endif
                        if ((GhostComponentIndex[baseOffset + comp].SendMask & requiredSendMask) == 0)
                        {
                            continue;
                        }

                        var compSize = GhostComponentCollection[serializerIdx].ComponentType.IsBuffer
                            ? GhostSystemConstants.DynamicBufferComponentSnapshotSize
                            : GhostComponentCollection[serializerIdx].ComponentSize;
                        var entityIdx = GhostComponentIndex[baseOffset + comp].EntityIndex;

                        for (int ent = 0; ent < chunk.Count; ++ent)
                        {
                            // If this entity did not predict anything there was no rollback and no need to debug it
                            if (!GhostPredictionSystemGroup.ShouldPredict(tick, predictedGhostComponents[ent]))
                            {
                                continue;
                            }
                            if (entities[ent] != backupEntities[ent])
                            {
                                continue;
                            }
                            var linkedEntityGroup = linkedEntityGroupAccessor[ent];
                            if (childEntityLookup.TryGetValue(linkedEntityGroup[entityIdx].Value, out var childChunk) &&
                                childChunk.chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                            {
                                if (!GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                                {
                                    var compData   = (byte *)childChunk.chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[compIdx], compSize).GetUnsafeReadOnlyPtr();
                                    int errorIndex = GhostComponentIndex[baseOffset + comp].PredictionErrorBaseIndex;
                                    var errors     = new UnsafeList <float>(((float *)predictionErrors.GetUnsafePtr()) + errorIndex + ThreadIndex * numPredictionErrors, numPredictionErrors - errorIndex);
                                    GhostComponentCollection[serializerIdx].ReportPredictionErrors.Ptr.Invoke((System.IntPtr)(compData + compSize * childChunk.index), (System.IntPtr)(dataPtr + compSize * ent), ref errors);
                                }
                                else
                                {
                                    //FIXME Buffers need to report error for the size and an aggregate for each element in the buffer
                                }
                            }
                        }

                        dataPtr = PredictionBackupState.GetNextData(dataPtr, compSize, chunk.Capacity);
                    }
                }
            }