public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var deserializerState = new GhostDeserializerState
            {
                GhostMap = GhostMap
            };
            var ghostEntityArray             = chunk.GetNativeArray(ghostEntityType);
            var ghostSnapshotDataArray       = chunk.GetBufferAccessor(ghostSnapshotDataType);
            var predictedGhostComponentArray = chunk.GetNativeArray(predictedGhostComponentType);
            var ghostHealthArray             = chunk.GetNativeArray(ghostHealthType);
            var ghostPlayerUnitArray         = chunk.GetNativeArray(ghostPlayerUnitType);
            var ghostUnitSelectionStateArray = chunk.GetNativeArray(ghostUnitSelectionStateType);
            var ghostLinkedEntityGroupArray  = chunk.GetBufferAccessor(ghostLinkedEntityGroupType);

#if UNITY_EDITOR || DEVELOPMENT_BUILD
            var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4);
#endif
            for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex)
            {
                var snapshot = ghostSnapshotDataArray[entityIndex];
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                var latestTick = snapshot.GetLatestTick();
                if (latestTick != 0)
                {
                    if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick))
                    {
                        minMaxSnapshotTick[minMaxOffset] = latestTick;
                    }
                    if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1]))
                    {
                        minMaxSnapshotTick[minMaxOffset + 1] = latestTick;
                    }
                }
#endif
                ACivilianSnapshotData snapshotData;
                snapshot.GetDataAtTick(targetTick, out snapshotData);

                var predictedData         = predictedGhostComponentArray[entityIndex];
                var lastPredictedTickInst = lastPredictedTick;
                if (lastPredictedTickInst == 0 || predictedData.AppliedTick != snapshotData.Tick)
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }
                else if (!SequenceHelpers.IsNewer(lastPredictedTickInst, snapshotData.Tick))
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }
                if (minPredictedTick[ThreadIndex] == 0 || SequenceHelpers.IsNewer(minPredictedTick[ThreadIndex], lastPredictedTickInst))
                {
                    minPredictedTick[ThreadIndex] = lastPredictedTickInst;
                }
                predictedGhostComponentArray[entityIndex] = new PredictedGhostComponent {
                    AppliedTick = snapshotData.Tick, PredictionStartTick = lastPredictedTickInst
                };
                if (lastPredictedTickInst != snapshotData.Tick)
                {
                    continue;
                }

                var ghostHealth             = ghostHealthArray[entityIndex];
                var ghostPlayerUnit         = ghostPlayerUnitArray[entityIndex];
                var ghostUnitSelectionState = ghostUnitSelectionStateArray[entityIndex];
                var ghostRotation           = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value];
                var ghostTranslation        = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value];
                var ghostChild0Rotation     = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value];
                var ghostChild0Translation  = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value];
                var ghostChild1Rotation     = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value];
                var ghostChild1Translation  = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value];
                ghostHealth.Value                  = snapshotData.GetHealthValue(deserializerState);
                ghostPlayerUnit.PlayerId           = snapshotData.GetPlayerUnitPlayerId(deserializerState);
                ghostPlayerUnit.UnitId             = snapshotData.GetPlayerUnitUnitId(deserializerState);
                ghostUnitSelectionState.IsSelected = snapshotData.GetUnitSelectionStateIsSelected(deserializerState);
                ghostRotation.Value                = snapshotData.GetRotationValue(deserializerState);
                ghostTranslation.Value             = snapshotData.GetTranslationValue(deserializerState);
                ghostChild0Rotation.Value          = snapshotData.GetChild0RotationValue(deserializerState);
                ghostChild0Translation.Value       = snapshotData.GetChild0TranslationValue(deserializerState);
                ghostChild1Rotation.Value          = snapshotData.GetChild1RotationValue(deserializerState);
                ghostChild1Translation.Value       = snapshotData.GetChild1TranslationValue(deserializerState);
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value]    = ghostRotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value] = ghostTranslation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value]    = ghostChild0Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value] = ghostChild0Translation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value]    = ghostChild1Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value] = ghostChild1Translation;
                ghostHealthArray[entityIndex]             = ghostHealth;
                ghostPlayerUnitArray[entityIndex]         = ghostPlayerUnit;
                ghostUnitSelectionStateArray[entityIndex] = ghostUnitSelectionState;
            }
        }
Exemplo n.º 2
0
            //Sum up all the dynamic buffers raw data content size. Each buffer content size is aligned to 16 bytes
            private int GetChunkBuffersDataSize(GhostCollectionPrefabSerializer typeData, ArchetypeChunk chunk,
                                                DynamicComponentTypeHandle *ghostChunkComponentTypesPtr, int ghostChunkComponentTypesLength, DynamicBuffer <GhostCollectionComponentIndex> GhostComponentIndex, DynamicBuffer <GhostComponentSerializer.State> GhostComponentCollection)
            {
                int numBaseComponents = typeData.NumComponents - typeData.NumChildComponents;
                int bufferTotalSize   = 0;
                int baseOffset        = typeData.FirstComponent;

                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;
                    }

                    if (!GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                    {
                        continue;
                    }

                    if (chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                    {
                        var bufferData = chunk.GetUntypedBufferAccessor(ref ghostChunkComponentTypesPtr[compIdx]);
                        for (int i = 0; i < bufferData.Length; ++i)
                        {
                            bufferTotalSize += bufferData.GetBufferCapacity(i) * GhostComponentCollection[serializerIdx].ComponentSize;
                        }
                        bufferTotalSize = GhostCollectionSystem.SnapshotSizeAligned(bufferTotalSize);
                    }
                }

                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;
                        }

                        if (!GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                        {
                            continue;
                        }

                        for (int ent = 0; ent < chunk.Count; ++ent)
                        {
                            var linkedEntityGroup = linkedEntityGroupAccessor[ent];
                            if (childEntityLookup.TryGetValue(linkedEntityGroup[GhostComponentIndex[baseOffset + comp].EntityIndex].Value,
                                                              out var childChunk) && childChunk.chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                            {
                                var bufferData = childChunk.chunk.GetUntypedBufferAccessor(ref ghostChunkComponentTypesPtr[compIdx]);
                                bufferTotalSize += bufferData.GetBufferCapacity(childChunk.index) * GhostComponentCollection[serializerIdx].ComponentSize;
                            }
                            bufferTotalSize = GhostCollectionSystem.SnapshotSizeAligned(bufferTotalSize);
                        }
                    }
                }

                return(bufferTotalSize);
            }
Exemplo n.º 3
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex, DynamicComponentTypeHandle *ghostChunkComponentTypesPtr, int ghostChunkComponentTypesLength)
            {
                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 singleEntitySize = UnsafeUtility.SizeOf <Entity>();
                int baseOffset       = typeData.FirstComponent;

                if (!predictionState.TryGetValue(chunk, out var state) ||
                    (*(PredictionBackupState *)state).ghostType != ghostTypeId ||
                    (*(PredictionBackupState *)state).entityCapacity != chunk.Capacity)
                {
                    int dataSize = 0;
                    // Sum up the size of all components rounded up
                    for (int comp = 0; 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;
                        }

                        //for buffers we store a a pair of uint:
                        // uint length: the num of elements
                        // uint backupDataOffset: the start position in the backup buffer
                        if (!GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                        {
                            dataSize += PredictionBackupState.GetDataSize(
                                GhostComponentCollection[serializerIdx].ComponentSize, chunk.Capacity);
                        }
                        else
                        {
                            dataSize += PredictionBackupState.GetDataSize(GhostSystemConstants.DynamicBufferComponentSnapshotSize, chunk.Capacity);
                        }
                    }

                    //compute the space necessary to store the dynamic buffers data for the chunk
                    int buffersDataCapacity = 0;
                    if (typeData.NumBuffers > 0)
                    {
                        buffersDataCapacity = GetChunkBuffersDataSize(typeData, chunk, ghostChunkComponentTypesPtr, ghostChunkComponentTypesLength, GhostComponentIndex, GhostComponentCollection);
                    }

                    // Chunk does not exist in the history, or has changed ghost type in which case we need to create a new one
                    state = PredictionBackupState.AllocNew(ghostTypeId, dataSize, chunk.Capacity, buffersDataCapacity);
                    newPredictionState.Enqueue(new PredictionStateEntry {
                        chunk = chunk, data = state
                    });
                }
                else
                {
                    stillUsedPredictionState.TryAdd(chunk, 1);
                    if (typeData.NumBuffers > 0)
                    {
                        //resize the backup state to fit the dynamic buffers contents
                        var buffersDataCapacity      = GetChunkBuffersDataSize(typeData, chunk, ghostChunkComponentTypesPtr, ghostChunkComponentTypesLength, GhostComponentIndex, GhostComponentCollection);
                        int bufferBackupDataCapacity = PredictionBackupState.GetBufferDataCapacity(state);
                        if (bufferBackupDataCapacity < buffersDataCapacity)
                        {
                            var dataSize = ((PredictionBackupState *)state)->dataSize;
                            var newState = PredictionBackupState.AllocNew(ghostTypeId, dataSize, chunk.Capacity, buffersDataCapacity);
                            UnsafeUtility.Free((void *)state, Allocator.Persistent);
                            state = newState;
                            updatedPredictionState.Enqueue(new PredictionStateEntry {
                                chunk = chunk, data = newState
                            });
                        }
                    }
                }
                Entity *entities    = PredictionBackupState.GetEntities(state);
                var     srcEntities = chunk.GetNativeArray(entityType).GetUnsafeReadOnlyPtr();
                UnsafeUtility.MemCpy(entities, srcEntities, chunk.Count * singleEntitySize);
                if (chunk.Count < chunk.Capacity)
                {
                    UnsafeUtility.MemClear(entities + chunk.Count, (chunk.Capacity - chunk.Count) * singleEntitySize);
                }

                byte *dataPtr             = PredictionBackupState.GetData(state);
                byte *bufferBackupDataPtr = PredictionBackupState.GetBufferDataPtr(state);

                int numBaseComponents      = typeData.NumComponents - typeData.NumChildComponents;
                int bufferBackupDataOffset = 0;
                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]))
                    {
                        UnsafeUtility.MemClear(dataPtr, chunk.Count * compSize);
                    }
                    else if (!GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                    {
                        var compData = (byte *)chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[compIdx], compSize).GetUnsafeReadOnlyPtr();
                        UnsafeUtility.MemCpy(dataPtr, compData, chunk.Count * compSize);
                    }
                    else
                    {
                        var bufferData  = chunk.GetUntypedBufferAccessor(ref ghostChunkComponentTypesPtr[compIdx]);
                        var bufElemSize = GhostComponentCollection[serializerIdx].ComponentSize;
                        //Use local variable to iterate and set the buffer offset and length. The dataptr must be
                        //advanced "per chunk" to the next correct position
                        var tempDataPtr = dataPtr;
                        for (int i = 0; i < bufferData.Length; ++i)
                        {
                            //Retrieve an copy each buffer data. Set size and offset in the backup buffer in the component backup
                            var bufferPtr = bufferData.GetUnsafeReadOnlyPtrAndLength(i, out var size);
                            ((int *)tempDataPtr)[0] = size;
                            ((int *)tempDataPtr)[1] = bufferBackupDataOffset;
                            if (size > 0)
                            {
                                UnsafeUtility.MemCpy(bufferBackupDataPtr + bufferBackupDataOffset, (byte *)bufferPtr, size * bufElemSize);
                            }
                            bufferBackupDataOffset += size * bufElemSize;
                            tempDataPtr            += compSize;
                        }
                        bufferBackupDataOffset = GhostCollectionSystem.SnapshotSizeAligned(bufferBackupDataOffset);
                    }
                    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 isBuffer = GhostComponentCollection[serializerIdx].ComponentType.IsBuffer;
                        var compSize = isBuffer ? GhostSystemConstants.DynamicBufferComponentSnapshotSize : GhostComponentCollection[serializerIdx].ComponentSize;
                        if (!GhostComponentCollection[serializerIdx].ComponentType.IsBuffer)
                        {
                            //use a temporary for the iteration here. Otherwise when the dataptr is offset for the chunk, we
                            //end up in the wrong position
                            var tempDataPtr = dataPtr;
                            for (int ent = 0; ent < chunk.Count; ++ent)
                            {
                                var linkedEntityGroup = linkedEntityGroupAccessor[ent];
                                if (childEntityLookup.TryGetValue(linkedEntityGroup[GhostComponentIndex[baseOffset + comp].EntityIndex].Value, out var childChunk) &&
                                    childChunk.chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                                {
                                    var compData = (byte *)childChunk.chunk.GetDynamicComponentDataArrayReinterpret <byte>(ghostChunkComponentTypesPtr[compIdx], compSize).GetUnsafeReadOnlyPtr();
                                    UnsafeUtility.MemCpy(tempDataPtr, compData + childChunk.index * compSize, compSize);
                                }
                                else
                                {
                                    UnsafeUtility.MemClear(tempDataPtr, compSize);
                                }
                                tempDataPtr += compSize;
                            }
                        }
                        else
                        {
                            var bufElemSize = GhostComponentCollection[serializerIdx].ComponentSize;
                            var tempDataPtr = dataPtr;
                            for (int ent = 0; ent < chunk.Count; ++ent)
                            {
                                var linkedEntityGroup = linkedEntityGroupAccessor[ent];
                                if (childEntityLookup.TryGetValue(linkedEntityGroup[GhostComponentIndex[baseOffset + comp].EntityIndex].Value, out var childChunk) &&
                                    childChunk.chunk.Has(ghostChunkComponentTypesPtr[compIdx]))
                                {
                                    var bufferData = childChunk.chunk.GetUntypedBufferAccessor(ref ghostChunkComponentTypesPtr[compIdx]);
                                    //Retrieve an copy each buffer data. Set size and offset in the backup buffer in the component backup
                                    var bufferPtr = bufferData.GetUnsafeReadOnlyPtrAndLength(childChunk.index, out var size);
                                    ((int *)tempDataPtr)[0] = size;
                                    ((int *)tempDataPtr)[1] = bufferBackupDataOffset;
                                    if (size > 0)
                                    {
                                        UnsafeUtility.MemCpy(bufferBackupDataPtr + bufferBackupDataOffset, (byte *)bufferPtr, size * bufElemSize);
                                    }
                                    bufferBackupDataOffset += size * bufElemSize;
                                }
                                else
                                {
                                    //reset the entry to 0. Don't use memcpy in this case (is faster this way)
                                    ((long *)tempDataPtr)[0] = 0;
                                }
                                tempDataPtr += compSize;
                            }
                            bufferBackupDataOffset = GhostCollectionSystem.SnapshotSizeAligned(bufferBackupDataOffset);
                        }
                        dataPtr = PredictionBackupState.GetNextData(dataPtr, compSize, chunk.Capacity);
                    }
                }
            }
Exemplo n.º 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])
                            {
                                int errorIndex = GhostComponentIndex[baseOffset + comp].PredictionErrorBaseIndex;

                                var errors = new UnsafeList <float>(((float *)predictionErrors.GetUnsafePtr()) + errorIndex + ThreadIndex * numPredictionErrors, numPredictionErrors - errorIndex);
                                GhostComponentCollection[compIdx].ReportPredictionErrors.Ptr.Invoke((System.IntPtr)(compData + compSize * ent), (System.IntPtr)(dataPtr + compSize * ent), ref errors);
                            }
                        }
                    }

                    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();
                                int errorIndex = GhostComponentIndex[baseOffset + comp].PredictionErrorBaseIndex;
                                var errors     = new UnsafeList <float>(((float *)predictionErrors.GetUnsafePtr()) + errorIndex + ThreadIndex * numPredictionErrors, numPredictionErrors - errorIndex);
                                GhostComponentCollection[compIdx].ReportPredictionErrors.Ptr.Invoke((System.IntPtr)(compData + compSize * childChunk.index), (System.IntPtr)(dataPtr + compSize * ent), ref errors);
                            }
                        }

                        dataPtr = PredictionBackupState.GetNextData(dataPtr, compSize, chunk.Capacity);
                    }
                }
            }
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var deserializerState = new GhostDeserializerState
            {
                GhostMap = GhostMap
            };
            var ghostEntityArray                = chunk.GetNativeArray(ghostEntityType);
            var ghostSnapshotDataArray          = chunk.GetBufferAccessor(ghostSnapshotDataType);
            var predictedGhostComponentArray    = chunk.GetNativeArray(predictedGhostComponentType);
            var ghostPlayerIdComponentDataArray = chunk.GetNativeArray(ghostPlayerIdComponentDataType);
            var ghostRotationArray              = chunk.GetNativeArray(ghostRotationType);
            var ghostTranslationArray           = chunk.GetNativeArray(ghostTranslationType);
            var ghostVelocityArray              = chunk.GetNativeArray(ghostVelocityType);

#if UNITY_EDITOR || DEVELOPMENT_BUILD
            var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4);
#endif
            for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex)
            {
                var snapshot = ghostSnapshotDataArray[entityIndex];
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                var latestTick = snapshot.GetLatestTick();
                if (latestTick != 0)
                {
                    if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick))
                    {
                        minMaxSnapshotTick[minMaxOffset] = latestTick;
                    }
                    if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1]))
                    {
                        minMaxSnapshotTick[minMaxOffset + 1] = latestTick;
                    }
                }
#endif
                ShipSnapshotData snapshotData;
                snapshot.GetDataAtTick(targetTick, out snapshotData);

                var predictedData         = predictedGhostComponentArray[entityIndex];
                var lastPredictedTickInst = lastPredictedTick;
                if (lastPredictedTickInst == 0 || predictedData.AppliedTick != snapshotData.Tick)
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }
                else if (!SequenceHelpers.IsNewer(lastPredictedTickInst, snapshotData.Tick))
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }
                if (minPredictedTick[ThreadIndex] == 0 || SequenceHelpers.IsNewer(minPredictedTick[ThreadIndex], lastPredictedTickInst))
                {
                    minPredictedTick[ThreadIndex] = lastPredictedTickInst;
                }
                predictedGhostComponentArray[entityIndex] = new PredictedGhostComponent {
                    AppliedTick = snapshotData.Tick, PredictionStartTick = lastPredictedTickInst
                };
                if (lastPredictedTickInst != snapshotData.Tick)
                {
                    continue;
                }

                var ghostPlayerIdComponentData = ghostPlayerIdComponentDataArray[entityIndex];
                var ghostRotation    = ghostRotationArray[entityIndex];
                var ghostTranslation = ghostTranslationArray[entityIndex];
                var ghostVelocity    = ghostVelocityArray[entityIndex];
                ghostPlayerIdComponentData.PlayerId = snapshotData.GetPlayerIdComponentDataPlayerId(deserializerState);
                ghostRotation.Value    = snapshotData.GetRotationValue(deserializerState);
                ghostTranslation.Value = snapshotData.GetTranslationValue(deserializerState);
                ghostVelocity.Value    = snapshotData.GetVelocityValue(deserializerState);
                ghostPlayerIdComponentDataArray[entityIndex] = ghostPlayerIdComponentData;
                ghostRotationArray[entityIndex]    = ghostRotation;
                ghostTranslationArray[entityIndex] = ghostTranslation;
                ghostVelocityArray[entityIndex]    = ghostVelocity;
            }
        }
Exemplo n.º 6
0
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            GhostDeserializerState deserializerState = new GhostDeserializerState
            {
                GhostMap = GhostMap
            };
            NativeArray <Entity> ghostEntityArray = chunk.GetNativeArray(ghostEntityType);
            BufferAccessor <NetCodeTestGhostObjectSnapshotData> ghostSnapshotDataArray =
                chunk.GetBufferAccessor(ghostSnapshotDataType);
            NativeArray <PredictedGhostComponent> predictedGhostComponentArray =
                chunk.GetNativeArray(predictedGhostComponentType);
            NativeArray <Rotation>    ghostRotationArray    = chunk.GetNativeArray(ghostRotationType);
            NativeArray <Translation> ghostTranslationArray = chunk.GetNativeArray(ghostTranslationType);

#if UNITY_EDITOR || DEVELOPMENT_BUILD
            int minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4);
#endif
            for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex)
            {
                DynamicBuffer <NetCodeTestGhostObjectSnapshotData> snapshot = ghostSnapshotDataArray[entityIndex];
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                uint latestTick = snapshot.GetLatestTick();
                if (latestTick != 0)
                {
                    if (minMaxSnapshotTick[minMaxOffset] == 0 ||
                        SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick))
                    {
                        minMaxSnapshotTick[minMaxOffset] = latestTick;
                    }

                    if (minMaxSnapshotTick[minMaxOffset + 1] == 0 ||
                        SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1]))
                    {
                        minMaxSnapshotTick[minMaxOffset + 1] = latestTick;
                    }
                }
#endif
                NetCodeTestGhostObjectSnapshotData snapshotData;
                snapshot.GetDataAtTick(targetTick, out snapshotData);

                PredictedGhostComponent predictedData = predictedGhostComponentArray[entityIndex];
                uint lastPredictedTickInst            = lastPredictedTick;
                if (lastPredictedTickInst == 0 || predictedData.AppliedTick != snapshotData.Tick)
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }
                else if (!SequenceHelpers.IsNewer(lastPredictedTickInst, snapshotData.Tick))
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }

                if (minPredictedTick[ThreadIndex] == 0 ||
                    SequenceHelpers.IsNewer(minPredictedTick[ThreadIndex], lastPredictedTickInst))
                {
                    minPredictedTick[ThreadIndex] = lastPredictedTickInst;
                }

                predictedGhostComponentArray[entityIndex] = new PredictedGhostComponent
                {
                    AppliedTick = snapshotData.Tick, PredictionStartTick = lastPredictedTickInst
                };
                if (lastPredictedTickInst != snapshotData.Tick)
                {
                    continue;
                }

                Rotation    ghostRotation    = ghostRotationArray[entityIndex];
                Translation ghostTranslation = ghostTranslationArray[entityIndex];
                ghostRotation.Value                = snapshotData.GetRotationValue(deserializerState);
                ghostTranslation.Value             = snapshotData.GetTranslationValue(deserializerState);
                ghostRotationArray[entityIndex]    = ghostRotation;
                ghostTranslationArray[entityIndex] = ghostTranslation;
            }
        }
Exemplo n.º 7
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                //Writeable.
                NativeArray <PathFinding> pathfindingArray       = chunk.GetNativeArray(pathFindingComponentHandle);
                BufferAccessor <PathNode> pathNodeBufferAccessor = chunk.GetBufferAccessor(pathNodeBufferHandle);

                //Read Only.
                NativeArray <CurrentTarget> currentTargetArray = chunk.GetNativeArray(currentTargetComponentHandle);
                NativeArray <Translation>   translationArray   = chunk.GetNativeArray(translationComponentHandle);
                NativeArray <Entity>        entities           = chunk.GetNativeArray(entityType);

                //Create a copy of the grid for this thread and chunk.
                NativeArray2D <MapNode> gridCopy = new NativeArray2D <MapNode>(gridRef.Length0, gridRef.Length1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

                UnsafeUtility.MemCpy(gridCopy.GetUnsafePtr(), gridRef.GetUnsafePtrReadOnly(), gridRef.Length * sizeof(MapNode));

                for (int indexInChunk = 0; indexInChunk < chunk.Count; ++indexInChunk)
                {
                    //Writable.
                    PathFinding pathfinding       = pathfindingArray[indexInChunk];
                    DynamicBuffer <PathNode> path = pathNodeBufferAccessor[indexInChunk];

                    //Read Only.
                    Entity        entity        = entities[indexInChunk];
                    CurrentTarget currentTarget = currentTargetArray[indexInChunk];
                    Translation   translation   = translationArray[indexInChunk];

                    bool hasPath = chunk.Has(hasPathComponentHandle);

                    if (!pathfinding.requestedPath)
                    {
                        //We only want to remove our has path component if we didn't request a new one, to avoid re-adding later in the job if we find a new path.
                        if (pathfinding.completedPath)
                        {
                            pathfinding.completedPath = false;
                            ecb.RemoveComponent <HasPathTag>(chunkIndex, entity);
                            pathfindingArray[indexInChunk] = pathfinding;
                        }

                        continue;
                    }

                    path.Clear();
                    pathfinding.currentIndexOnPath = 0;
                    pathfinding.completedPath      = false;
                    pathfinding.requestedPath      = false;

                    //Calculate the closest nodes to us and our target position.
                    //Don't search for path if we're already at our target node.
                    pathfinding.currentNode = MapUtils.FindNearestNode(translation.Value, gridCopy);
                    pathfinding.targetNode  = MapUtils.FindNearestNode(currentTarget.targetData.targetPos, gridCopy);
                    if (pathfinding.targetNode.Equals(pathfinding.currentNode))
                    {
                        pathfindingArray[indexInChunk] = pathfinding;
                        continue;
                    }

                    CalculateGridH(gridCopy, ref pathfinding);

                    bool pathfound = SearchForPath(pathfinding.currentNode, pathfinding.targetNode, gridCopy);

                    if (pathfound)
                    {
                        ConstructPath(gridCopy, ref pathfinding, ref path);

                        if (!hasPath)
                        {
                            ecb.AddComponent <HasPathTag>(chunkIndex, entity);
                        }
                    }
                    else if (hasPath)
                    {
                        ecb.RemoveComponent <HasPathTag>(chunkIndex, entity);
                    }

                    pathfindingArray[indexInChunk] = pathfinding;
                }

                gridCopy.Dispose();
            }
        public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            float3 up = math.up();

            var chunkCCData              = chunk.GetNativeArray(CharacterControllerComponentType);
            var chunkCCInternalData      = chunk.GetNativeArray(CharacterControllerInternalType);
            var chunkPhysicsColliderData = chunk.GetNativeArray(PhysicsColliderType);
            var chunkTranslationData     = chunk.GetNativeArray(TranslationType);
            var chunkRotationData        = chunk.GetNativeArray(RotationType);

            var hasChunkCollisionEventBufferType = chunk.Has(CollisionEventBufferType);
            var hasChunkTriggerEventBufferType   = chunk.Has(TriggerEventBufferType);

            BufferAccessor <StatefulCollisionEvent> collisionEventBuffers = default;
            BufferAccessor <StatefulTriggerEvent>   triggerEventBuffers   = default;

            if (hasChunkCollisionEventBufferType)
            {
                collisionEventBuffers = chunk.GetBufferAccessor(CollisionEventBufferType);
            }
            if (hasChunkTriggerEventBufferType)
            {
                triggerEventBuffers = chunk.GetBufferAccessor(TriggerEventBufferType);
            }

            DeferredImpulseWriter.BeginForEachIndex(chunkIndex);

            for (int i = 0; i < chunk.Count; i++)
            {
                var ccComponentData = chunkCCData[i];
                var ccInternalData  = chunkCCInternalData[i];
                var collider        = chunkPhysicsColliderData[i];
                var position        = chunkTranslationData[i];
                var rotation        = chunkRotationData[i];
                DynamicBuffer <StatefulCollisionEvent> collisionEventBuffer = default;
                DynamicBuffer <StatefulTriggerEvent>   triggerEventBuffer   = default;

                if (hasChunkCollisionEventBufferType)
                {
                    collisionEventBuffer = collisionEventBuffers[i];
                }

                if (hasChunkTriggerEventBufferType)
                {
                    triggerEventBuffer = triggerEventBuffers[i];
                }

                // Collision filter must be valid
                if (!collider.IsValid || collider.Value.Value.Filter.IsEmpty)
                {
                    continue;
                }

                // Character step input
                CharacterControllerStepInput stepInput = new CharacterControllerStepInput
                {
                    World            = PhysicsWorld,
                    DeltaTime        = DeltaTime,
                    Up               = math.up(),
                    Gravity          = ccComponentData.Gravity,
                    MaxIterations    = ccComponentData.MaxIterations,
                    Tau              = k_DefaultTau,
                    Damping          = k_DefaultDamping,
                    SkinWidth        = ccComponentData.SkinWidth,
                    ContactTolerance = ccComponentData.ContactTolerance,
                    MaxSlope         = ccComponentData.MaxSlope,
                    RigidBodyIndex   = PhysicsWorld.GetRigidBodyIndex(ccInternalData.Entity),
                    CurrentVelocity  = ccInternalData.LinearVelocity,
                    MaxMovementSpeed = ccComponentData.MaxMovementSpeed
                };

                // Character transform
                RigidTransform transform = new RigidTransform
                {
                    pos = position.Value,
                    rot = rotation.Value
                };

                NativeList <StatefulCollisionEvent> currentFrameCollisionEvents = default;
                NativeList <StatefulTriggerEvent>   currentFrameTriggerEvents   = default;

                if (ccComponentData.RaiseCollisionEvents != 0)
                {
                    currentFrameCollisionEvents = new NativeList <StatefulCollisionEvent>(Allocator.Temp);
                }

                if (ccComponentData.RaiseTriggerEvents != 0)
                {
                    currentFrameTriggerEvents = new NativeList <StatefulTriggerEvent>(Allocator.Temp);
                }


                // Check support
                CheckSupport(ref PhysicsWorld, ref collider, stepInput, transform,
                             out ccInternalData.SupportedState, out float3 surfaceNormal, out float3 surfaceVelocity,
                             currentFrameCollisionEvents);

                // User input
                float3 desiredVelocity = ccInternalData.LinearVelocity;
                HandleUserInput(ccComponentData, stepInput.Up, surfaceVelocity, ref ccInternalData, ref desiredVelocity);

                // Calculate actual velocity with respect to surface
                if (ccInternalData.SupportedState == CharacterSupportState.Supported)
                {
                    CalculateMovement(ccInternalData.CurrentRotationAngle, stepInput.Up, ccInternalData.IsJumping,
                                      ccInternalData.LinearVelocity, desiredVelocity, surfaceNormal, surfaceVelocity, out ccInternalData.LinearVelocity);
                }
                else
                {
                    ccInternalData.LinearVelocity = desiredVelocity;
                }

                // World collision + integrate
                CollideAndIntegrate(stepInput, ccComponentData.CharacterMass, ccComponentData.AffectsPhysicsBodies != 0,
                                    collider.ColliderPtr, ref transform, ref ccInternalData.LinearVelocity, ref DeferredImpulseWriter,
                                    currentFrameCollisionEvents, currentFrameTriggerEvents);

                // Update collision event status
                if (currentFrameCollisionEvents.IsCreated)
                {
                    UpdateCollisionEvents(currentFrameCollisionEvents, collisionEventBuffer);
                }

                if (currentFrameTriggerEvents.IsCreated)
                {
                    UpdateTriggerEvents(currentFrameTriggerEvents, triggerEventBuffer);
                }

                // Write back and orientation integration
                position.Value = transform.pos;
                rotation.Value = quaternion.AxisAngle(up, ccInternalData.CurrentRotationAngle);

                // Write back to chunk data
                {
                    chunkCCInternalData[i]  = ccInternalData;
                    chunkTranslationData[i] = position;
                    chunkRotationData[i]    = rotation;
                }
            }

            DeferredImpulseWriter.EndForEachIndex();
        }
Exemplo n.º 9
0
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var deserializerState = new GhostDeserializerState
            {
                GhostMap = GhostMap
            };
            var ghostEntityArray            = chunk.GetNativeArray(ghostEntityType);
            var ghostSnapshotDataArray      = chunk.GetBufferAccessor(ghostSnapshotDataType);
            var ghostPilotDataArray         = chunk.GetNativeArray(ghostPilotDataType);
            var ghostLinkedEntityGroupArray = chunk.GetBufferAccessor(ghostLinkedEntityGroupType);

#if UNITY_EDITOR || DEVELOPMENT_BUILD
            var minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4);
#endif
            for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex)
            {
                var snapshot = ghostSnapshotDataArray[entityIndex];
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                var latestTick = snapshot.GetLatestTick();
                if (latestTick != 0)
                {
                    if (minMaxSnapshotTick[minMaxOffset] == 0 || SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick))
                    {
                        minMaxSnapshotTick[minMaxOffset] = latestTick;
                    }
                    if (minMaxSnapshotTick[minMaxOffset + 1] == 0 || SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1]))
                    {
                        minMaxSnapshotTick[minMaxOffset + 1] = latestTick;
                    }
                }
#endif
                // If there is no data found don't apply anything (would be default state), required for prespawned ghosts
                PilotSnapshotData snapshotData;
                if (!snapshot.GetDataAtTick(targetTick, targetTickFraction, out snapshotData))
                {
                    return;
                }

                var ghostPilotData         = ghostPilotDataArray[entityIndex];
                var ghostRotation          = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value];
                var ghostTranslation       = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value];
                var ghostChild0Rotation    = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value];
                var ghostChild0Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value];
                var ghostChild1Rotation    = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value];
                var ghostChild1Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value];
                var ghostChild2Rotation    = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][3].Value];
                var ghostChild2Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][3].Value];
                var ghostChild3Rotation    = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][4].Value];
                var ghostChild3Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][4].Value];
                var ghostChild4Rotation    = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][5].Value];
                var ghostChild4Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][5].Value];
                var ghostChild5Rotation    = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][6].Value];
                var ghostChild5Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][6].Value];
                var ghostChild6Rotation    = ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][7].Value];
                var ghostChild6Translation = ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][7].Value];
                ghostPilotData.PlayerId      = snapshotData.GetPilotDataPlayerId(deserializerState);
                ghostRotation.Value          = snapshotData.GetRotationValue(deserializerState);
                ghostTranslation.Value       = snapshotData.GetTranslationValue(deserializerState);
                ghostChild0Rotation.Value    = snapshotData.GetChild0RotationValue(deserializerState);
                ghostChild0Translation.Value = snapshotData.GetChild0TranslationValue(deserializerState);
                ghostChild1Rotation.Value    = snapshotData.GetChild1RotationValue(deserializerState);
                ghostChild1Translation.Value = snapshotData.GetChild1TranslationValue(deserializerState);
                ghostChild2Rotation.Value    = snapshotData.GetChild2RotationValue(deserializerState);
                ghostChild2Translation.Value = snapshotData.GetChild2TranslationValue(deserializerState);
                ghostChild3Rotation.Value    = snapshotData.GetChild3RotationValue(deserializerState);
                ghostChild3Translation.Value = snapshotData.GetChild3TranslationValue(deserializerState);
                ghostChild4Rotation.Value    = snapshotData.GetChild4RotationValue(deserializerState);
                ghostChild4Translation.Value = snapshotData.GetChild4TranslationValue(deserializerState);
                ghostChild5Rotation.Value    = snapshotData.GetChild5RotationValue(deserializerState);
                ghostChild5Translation.Value = snapshotData.GetChild5TranslationValue(deserializerState);
                ghostChild6Rotation.Value    = snapshotData.GetChild6RotationValue(deserializerState);
                ghostChild6Translation.Value = snapshotData.GetChild6TranslationValue(deserializerState);
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value]    = ghostRotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][0].Value] = ghostTranslation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value]    = ghostChild0Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][1].Value] = ghostChild0Translation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value]    = ghostChild1Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][2].Value] = ghostChild1Translation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][3].Value]    = ghostChild2Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][3].Value] = ghostChild2Translation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][4].Value]    = ghostChild3Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][4].Value] = ghostChild3Translation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][5].Value]    = ghostChild4Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][5].Value] = ghostChild4Translation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][6].Value]    = ghostChild5Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][6].Value] = ghostChild5Translation;
                ghostRotationFromEntity[ghostLinkedEntityGroupArray[entityIndex][7].Value]    = ghostChild6Rotation;
                ghostTranslationFromEntity[ghostLinkedEntityGroupArray[entityIndex][7].Value] = ghostChild6Translation;
                ghostPilotDataArray[entityIndex] = ghostPilotData;
            }
        }
Exemplo n.º 10
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                BuildMeshProfiler.Begin();

                var dimensions     = chunk.GetNativeArray(DimensionType);
                var vertexBuffer   = chunk.GetBufferAccessor(VertexType);
                var triangleBuffer = chunk.GetBufferAccessor(TriangleType);
                var colors         = chunk.GetNativeArray(ColorType);
                var entities       = chunk.GetNativeArray(EntityType);
                var spriteData     = chunk.GetNativeArray(SpriteDataType);
                var resolutions    = chunk.GetNativeArray(SpriteResType);

                for (int i = 0; i < chunk.Count; i++)
                {
                    var dimension  = dimensions[i];
                    var indices    = triangleBuffer[i];
                    var vertices   = vertexBuffer[i];
                    var color      = colors[i].Value.ToNormalizedFloat4();
                    var entity     = entities[i];
                    var spriteInfo = spriteData[i];
                    var resolution = resolutions[i].Value;

                    var spriteScale = (float2)(dimension.Value) / resolution;

                    indices.Clear();
                    vertices.Clear();

                    var right   = new float3(1, 0, 0);
                    var extents = dimension.Extents();

                    var outer   = spriteInfo.OuterUV;
                    var padding = spriteInfo.Padding;

                    var bl = -extents;

                    var spriteW = dimension.Width();
                    var spriteH = dimension.Height();

                    var pixelAdjustments = new float4(
                        (padding.x * spriteScale.x) / spriteW,
                        (padding.y * spriteScale.y) / spriteH,
                        (spriteW - padding.z * spriteScale.x) / spriteW,
                        (spriteH - padding.w * spriteScale.y) / spriteH
                        );

                    var pixelYAdjust = spriteScale.y * 1.5f;
                    var topAdjust    = spriteScale.y * (padding.w > 0 ? 1f : 0f);
                    var bottomAdjust = spriteScale.y * (padding.y > 0 ? 1f : 0f);

                    var v = new float4(
                        bl.x + spriteW * pixelAdjustments.x,
                        (bl.y + spriteH * pixelAdjustments.y) + bottomAdjust,
                        bl.x + spriteW * pixelAdjustments.z,
                        (bl.y + spriteH * pixelAdjustments.w) - topAdjust
                        );

                    vertices.Add(new MeshVertexData {
                        Position = new float3(v.xy, 0),
                        Normal   = right,
                        Color    = color,
                        UV1      = outer.xy,
                        UV2      = new float2(1)
                    });
                    vertices.Add(new MeshVertexData {
                        Position = new float3(v.xw, 0),
                        Normal   = right,
                        Color    = color,
                        UV1      = outer.xw,
                        UV2      = new float2(1)
                    });
                    vertices.Add(new MeshVertexData {
                        Position = new float3(v.zw, 0),
                        Normal   = right,
                        Color    = color,
                        UV1      = outer.zw,
                        UV2      = new float2(1)
                    });
                    vertices.Add(new MeshVertexData {
                        Position = new float3(v.zy, 0),
                        Normal   = right,
                        Color    = color,
                        UV1      = outer.zy,
                        UV2      = new float2(1)
                    });

                    // TODO: Figure this out mathematically instead of hard coding
                    // batched meshes need to be figured out and rebuilt...
                    indices.Add(new TriangleIndexElement {
                        Value = 0
                    });
                    indices.Add(new TriangleIndexElement {
                        Value = 1
                    });
                    indices.Add(new TriangleIndexElement {
                        Value = 2
                    });
                    indices.Add(new TriangleIndexElement {
                        Value = 0
                    });
                    indices.Add(new TriangleIndexElement {
                        Value = 2
                    });
                    indices.Add(new TriangleIndexElement {
                        Value = 3
                    });

                    CmdBuffer.AddComponent <CachedMeshTag>(entity.Index, entity);
                }
                BuildMeshProfiler.End();
            }