コード例 #1
0
 public void Execute()
 {
     UnsafeList.Destroy(vertices);
     UnsafeList.Destroy(chainedIndices);
     UnsafeUtility.Free(hashTable, allocator);
 }
コード例 #2
0
        public unsafe void Execute(int i)
        {
            float3 currentPos = Positions[i].Value;
            float3 currentDir = VehicleData[i].Forward;

            #region SpeedVariation
            float prevDistanceAhead = VehicleData[i].HitDistAhead;
            float newDistanceAhead  = HitResult[i].FrontHitDistance;
            float distAheadDiff     = prevDistanceAhead - newDistanceAhead;
            int   hitResult         = HitResult[i].HitResultPacked;
            float maxSpeed          = RoadSegments[VehicleData[i].SegId].MaxSpeed;
            float newSpeed          = VehicleData[i].Speed;
            if (hitResult == 0 && newSpeed < maxSpeed)
            {
                newSpeed += 0.5f;
            }
            else if ((hitResult & 0x1) == 1 && (distAheadDiff > 0))
            {
                newSpeed -= (distAheadDiff / 2.0f);
            }

            if (newDistanceAhead < 5.0f)
            {
                newSpeed -= 0.2f;
            }

            newSpeed = newSpeed > maxSpeed ? maxSpeed : newSpeed;
            newSpeed = newSpeed < 0 ? 0 : newSpeed;
            #endregion

            float stepLength  = newSpeed * DeltaTime;
            float segLength   = RoadSegments[VehicleData[i].SegId].Length;
            float stepPerc    = stepLength / segLength;
            float nextPosPerc = VehicleData[i].CurrentSegPos + stepPerc * VehicleData[i].Direction;

            Unity.Mathematics.Random rdGen = new Unity.Mathematics.Random();
            rdGen.InitState(FrameSeed + RandSeed[i]);

            #region switchLane

            int laneCount   = RoadSegments[VehicleData[i].SegId].LaneNumber;
            int currentLane = VehicleData[i].Lane;
            int laneSwitch  = rdGen.NextInt(-10, 10);
            laneSwitch = laneSwitch / 10;
            if (currentLane == 0 && laneSwitch == -1)
            {
                laneSwitch = 0;
            }
            if (currentLane == (laneCount - 1) && laneSwitch == 1)
            {
                laneSwitch = 0;
            }
            int nextLane = VehicleData[i].Lane + laneSwitch;
            #endregion

            //great, still in this seg
            if (nextPosPerc < 1.0f && nextPosPerc > 0.0f)
            {
                //step forward
                float3 nextPos = currentPos + currentDir * stepLength;
                //offset lane
                nextPos += laneSwitch * VehicleData[i].Direction * RoadSegments[VehicleData[i].SegId].LaneWidth *
                           RoadSegments[VehicleData[i].SegId].RightDirection;
                VehicleData[i] = new VehicleData(
                    VehicleData[i].Id,
                    VehicleData[i].SegId,
                    newSpeed,
                    VehicleData[i].Forward,
                    nextPosPerc,
                    VehicleData[i].Direction,
                    nextPos,
                    nextLane,
                    newDistanceAhead
                    );

                AABB newAABB = AABB[i];
                newAABB.Max += currentDir * stepLength;
                newAABB.Min += currentDir * stepLength;
                AABB[i]      = newAABB;

                Positions[i] = new Position()
                {
                    Value = nextPos
                };
            }
            //reach end node, find next seg
            else
            {
                int currentSeg  = VehicleData[i].SegId;
                int reachedNode = VehicleData[i].Direction > 0.0f ? RoadSegments[currentSeg].EndNodeId : RoadSegments[currentSeg].StartNodeId;

                //find next available segment
                int *_availableSeg = (int *)UnsafeUtility.Malloc(
                    5 * sizeof(int), sizeof(int), Allocator.Temp);
                int availableSegCount = 0;
                for (int k = 0; k < 3; k++)
                {
                    int seg1 = RoadNodes[reachedNode].ConnectionSegIds[k].x;
                    int seg2 = RoadNodes[reachedNode].ConnectionSegIds[k].y;
                    if (seg1 != -1 && seg1 != currentSeg && //not current seg, and next seg not one-way
                        !(RoadSegments[seg1].EndNodeId == reachedNode && RoadSegments[seg1].IsOneWay == 1))
                    {
                        _availableSeg[availableSegCount++] = seg1;
                    }
                    if (seg2 != -1 && seg2 != currentSeg && //not current seg, and next seg not one-way
                        !(RoadSegments[seg2].EndNodeId == reachedNode && RoadSegments[seg2].IsOneWay == 1))
                    {
                        _availableSeg[availableSegCount++] = seg2;
                    }
                }

                int   nextSeg = currentSeg;
                float dir     = 1.0f;
                if (availableSegCount > 0)//luckily we can proceed
                {
                    int selectSegId = rdGen.NextInt(0, availableSegCount);
                    nextSeg = _availableSeg[selectSegId];
                    dir     = RoadSegments[nextSeg].StartNodeId == reachedNode ? 1.0f : -1.0f;
                }
                else//to the end, spawn a new pos
                {
                    nextSeg = rdGen.NextInt(0, RoadSegments.Length);
                }

                float3     nextForward = RoadSegments[nextSeg].Direction * dir;
                quaternion newRot      = quaternion.LookRotation(nextForward, new float3()
                {
                    x = 0, y = 1, z = 0
                });

                laneCount = RoadSegments[nextSeg].LaneNumber;
                nextLane  = nextLane < laneCount ? nextLane : laneCount - 1;
                float laneOffset = (nextLane + 0.5f) * RoadSegments[nextSeg].LaneWidth;
                if (RoadSegments[nextSeg].IsOneWay == 1)
                {
                    laneOffset -= (laneCount / 2.0f) * RoadSegments[nextSeg].LaneWidth;
                }

                float nextPerct = dir > 0.0f
                    ? (nextPosPerc > 0.0f ? nextPosPerc - 1.0f : -nextPosPerc)
                    : (nextPosPerc > 0.0f ? 2.0f - nextPosPerc : nextPosPerc + 1.0f);

                float3 nextPos = (1.0f - nextPerct) * RoadNodes[RoadSegments[nextSeg].StartNodeId].Position +
                                 (nextPerct) * RoadNodes[RoadSegments[nextSeg].EndNodeId].Position;
                nextPos += laneOffset * dir * RoadSegments[nextSeg].RightDirection;

                VehicleData[i] = new VehicleData(
                    VehicleData[i].Id,
                    nextSeg,
                    newSpeed,
                    nextForward,
                    nextPerct,
                    dir,
                    nextPos,
                    nextLane,
                    newDistanceAhead
                    );

                AABB newAABB = AABB[i];
                newAABB.Max += (nextPos - currentPos);
                newAABB.Min += (nextPos - currentPos);
                AABB[i]      = newAABB;

                Positions[i] = new Position()
                {
                    Value = nextPos
                };
                Rotations[i] = new Rotation()
                {
                    Value = newRot
                };

                UnsafeUtility.Free(_availableSeg, Allocator.Temp);
                _availableSeg = null;
            }
        }
コード例 #3
0
        public void DestroyEntities(Entity *entities, int count)
        {
            var entityIndex = 0;

            var additionalDestroyList = new UnsafeList(Allocator.Persistent);
            int minDestroyStride      = int.MaxValue;
            int maxDestroyStride      = 0;

            while (entityIndex != count)
            {
                var entityBatchInChunk =
                    GetFirstEntityBatchInChunk(entities + entityIndex, count - entityIndex);
                var chunk        = entityBatchInChunk.Chunk;
                var batchCount   = entityBatchInChunk.Count;
                var indexInChunk = entityBatchInChunk.StartIndex;

                if (chunk == null)
                {
                    entityIndex += batchCount;
                    continue;
                }

                AddToDestroyList(chunk, indexInChunk, batchCount, count, ref additionalDestroyList,
                                 ref minDestroyStride, ref maxDestroyStride);

                DestroyBatch(entities + entityIndex, chunk, indexInChunk, batchCount);

                entityIndex += batchCount;
            }

            // Apply additional destroys from any LinkedEntityGroup
            if (additionalDestroyList.Ptr != null)
            {
                var additionalDestroyPtr = (Entity *)additionalDestroyList.Ptr;
                // Optimal for destruction speed is if entities with same archetype/chunk are followed one after another.
                // So we lay out the to be destroyed objects assuming that the destroyed entities are "similar":
                // Reorder destruction by index in entityGroupArray...

                //@TODO: This is a very specialized fastpath that is likely only going to give benefits in the stress test.
                ///      Figure out how to make this more general purpose.
                if (minDestroyStride == maxDestroyStride)
                {
                    var reordered = (Entity *)UnsafeUtility.Malloc(additionalDestroyList.Length * sizeof(Entity), 16,
                                                                   Allocator.TempJob);
                    int batchCount = additionalDestroyList.Length / minDestroyStride;
                    for (int i = 0; i != batchCount; i++)
                    {
                        for (int j = 0; j != minDestroyStride; j++)
                        {
                            reordered[j * batchCount + i] = additionalDestroyPtr[i * minDestroyStride + j];
                        }
                    }

                    DestroyEntities(reordered, additionalDestroyList.Length);
                    UnsafeUtility.Free(reordered, Allocator.TempJob);
                }
                else
                {
                    DestroyEntities(additionalDestroyPtr, additionalDestroyList.Length);
                }

                UnsafeUtility.Free(additionalDestroyPtr, Allocator.Persistent);
            }
        }
コード例 #4
0
 public void Dispose()
 {
     UnsafeUtility.Free(s, Allocator.Temp);
 }
コード例 #5
0
        public static unsafe void SerializeWorld(EntityManager entityManager, BinaryWriter writer, out int[] sharedComponentsToSerialize)
        {
            writer.Write(CurrentFileFormatVersion);
            var archetypeManager = entityManager.ArchetypeManager;

            GetAllArchetypes(archetypeManager, out var archetypeToIndex, out var archetypeArray);

            var typeindices = new HashSet <int>();

            foreach (var archetype in archetypeArray)
            {
                for (int iType = 0; iType < archetype.Archetype->TypesCount; ++iType)
                {
                    typeindices.Add(archetype.Archetype->Types[iType].TypeIndex);
                }
            }

            var typeArray = typeindices.Select(index =>
            {
                var type = TypeManager.GetType(index);
                var name = TypeManager.GetType(index).AssemblyQualifiedName;
                var hash = TypeManager.GetTypeInfo(index).FastEqualityTypeInfo.Hash;
                return(new
                {
                    index,
                    type,
                    name,
                    hash,
                    asciiName = Encoding.ASCII.GetBytes(name)
                });
            }).OrderBy(t => t.name).ToArray();

            int typeNameBufferSize = typeArray.Sum(t => t.asciiName.Length + 1);

            writer.Write(typeArray.Length);
            foreach (var n in typeArray)
            {
                writer.Write(n.hash);
            }

            writer.Write(typeNameBufferSize);
            foreach (var n in typeArray)
            {
                writer.Write(n.asciiName);
                writer.Write((byte)0);
            }

            var typeIndexMap = new Dictionary <int, int>();

            for (int i = 0; i < typeArray.Length; ++i)
            {
                typeIndexMap[typeArray[i].index] = i;
            }

            WriteArchetypes(writer, archetypeArray, typeIndexMap);

            //TODO: ensure chunks are defragged?

            NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapInfos;
            var bufferPatches   = new NativeList <BufferPatchRecord>(128, Allocator.Temp);
            var totalChunkCount = GenerateRemapInfo(entityManager, archetypeArray, out entityRemapInfos);

            writer.Write(totalChunkCount);

            var tempChunk = (Chunk *)UnsafeUtility.Malloc(Chunk.kChunkSize, 16, Allocator.Temp);

            var sharedIndexToSerialize = new Dictionary <int, int>();

            for (int archetypeIndex = 0; archetypeIndex < archetypeArray.Length; ++archetypeIndex)
            {
                var archetype = archetypeArray[archetypeIndex].Archetype;
                for (var c = (Chunk *)archetype->ChunkList.Begin; c != archetype->ChunkList.End; c = (Chunk *)c->ChunkListNode.Next)
                {
                    bufferPatches.Clear();

                    UnsafeUtility.MemCpy(tempChunk, c, Chunk.kChunkSize);
                    tempChunk->SharedComponentValueArray = (int *)((byte *)(tempChunk) + Chunk.GetSharedComponentOffset(archetype->NumSharedComponents));

                    byte *tempChunkBuffer = tempChunk->Buffer;

                    // Find all buffer pointer locations and work out how much memory the deserializer must allocate on load.
                    for (int ti = 0; ti < archetype->TypesCount; ++ti)
                    {
                        int index = archetype->TypeMemoryOrder[ti];

                        if (!archetype->Types[index].IsBuffer)
                        {
                            continue;
                        }

                        int           subArrayOffset = archetype->Offsets[index];
                        BufferHeader *header         = (BufferHeader *)OffsetFromPointer(tempChunkBuffer, subArrayOffset);
                        int           stride         = archetype->SizeOfs[index];
                        int           count          = c->Count;
                        var           ct             = TypeManager.GetTypeInfo(archetype->Types[index].TypeIndex);

                        for (int bi = 0; bi < count; ++bi)
                        {
                            if (header->Pointer != null)
                            {
                                header->Pointer = null;
                                bufferPatches.Add(new BufferPatchRecord
                                {
                                    ChunkOffset    = (int)(((byte *)header) - (byte *)tempChunkBuffer),
                                    AllocSizeBytes = ct.ElementSize * header->Capacity,
                                });
                            }
                            header = (BufferHeader *)OffsetFromPointer(header, stride);
                        }
                    }

                    EntityRemapUtility.PatchEntities(archetype->ScalarEntityPatches, archetype->ScalarEntityPatchCount, archetype->BufferEntityPatches, archetype->BufferEntityPatchCount, tempChunkBuffer, tempChunk->Count, ref entityRemapInfos);

                    ClearUnusedChunkData(tempChunk);
                    tempChunk->ChunkListNode.Next = null;
                    tempChunk->ChunkListNode.Prev = null;
                    tempChunk->ChunkListWithEmptySlotsNode.Next = null;
                    tempChunk->ChunkListWithEmptySlotsNode.Prev = null;
                    tempChunk->Archetype = (Archetype *)archetypeIndex;

                    if (archetype->NumManagedArrays != 0)
                    {
                        throw new ArgumentException("Serialization of GameObject components is not supported for pure entity scenes");
                    }

                    for (int i = 0; i != archetype->NumSharedComponents; i++)
                    {
                        int sharedComponentIndex = tempChunk->SharedComponentValueArray[i];
                        int newIndex;

                        if (tempChunk->SharedComponentValueArray[i] != 0)
                        {
                            if (sharedIndexToSerialize.TryGetValue(sharedComponentIndex, out newIndex))
                            {
                                tempChunk->SharedComponentValueArray[i] = newIndex;
                            }
                            else
                            {
                                // 0 is reserved for null types in shared components
                                newIndex = sharedIndexToSerialize.Count + 1;
                                sharedIndexToSerialize[sharedComponentIndex] = newIndex;

                                tempChunk->SharedComponentValueArray[i] = newIndex;
                            }
                        }
                    }

                    writer.WriteBytes(tempChunk, Chunk.kChunkSize);

                    writer.Write(bufferPatches.Length);

                    if (bufferPatches.Length > 0)
                    {
                        writer.WriteList(bufferPatches);

                        // Write heap backed data for each required patch.
                        // TODO: PERF: Investigate static-only deserialization could manage one block and mark in pointers somehow that they are not indiviual
                        for (int i = 0; i < bufferPatches.Length; ++i)
                        {
                            var patch = bufferPatches[i];
                            // NOTE that this reads the pointer from the original, unpatched chunk.
                            // We have nulled out the pointer in the serialized data above.
                            var header = (BufferHeader *)OffsetFromPointer(c->Buffer, patch.ChunkOffset);
                            writer.WriteBytes(header->Pointer, patch.AllocSizeBytes);
                        }
                    }
                }
            }

            bufferPatches.Dispose();
            entityRemapInfos.Dispose();
            UnsafeUtility.Free(tempChunk, Allocator.Temp);

            sharedComponentsToSerialize = new int[sharedIndexToSerialize.Count];

            foreach (var i in sharedIndexToSerialize)
            {
                sharedComponentsToSerialize[i.Value - 1] = i.Key;
            }
        }
コード例 #6
0
        public override void AdvanceFrame()
        {
            _sync.IncrementFrame();
            _current_input.Clear();

            Debug.Log($"End of frame({_sync.FrameCount})...");

            if (_rollingback)
            {
                return;
            }

            int frame = _sync.FrameCount;
            // Hold onto the current frame in our queue of saved states.  We'll need
            // the Checksum later to verify that our replay of the same frame got the
            // same results.
            var info = new SavedInfo {
                Frame  = frame,
                Input  = _last_input,
                Size   = _sync.GetLastSavedFrame().Size,
                Buffer = (byte *)UnsafeUtility.Malloc(_sync.GetLastSavedFrame().Size,
                                                      UnsafeUtility.AlignOf <byte>(),
                                                      Allocator.Temp),
                Checksum = _sync.GetLastSavedFrame().Checksum,
            };

            UnsafeUtility.MemCpy(info.Buffer, _sync.GetLastSavedFrame().Buffer, info.Size);
            _saved_frames.Push(info);

            if (frame - _last_verified == _check_distance)
            {
                // We've gone far enough ahead and should now start replaying frames.
                // Load the last verified frame and set the rollback flag to true.
                _sync.LoadFrame(_last_verified);

                _rollingback = true;
                while (!_saved_frames.IsEmpty)
                {
                    _callbacks.AdvanceFrame();

                    // Verify that the Checksumn of this frame is the same as the one in our
                    // list.
                    info = _saved_frames.Peek();
                    _saved_frames.Pop();

                    if (info.Frame != _sync.FrameCount)
                    {
                        Debug.LogWarning($"SyncTest: Frame number {info.Frame} does not match saved frame number {frame}");
                    }
                    int Checksum = _sync.GetLastSavedFrame().Checksum;
                    if (info.Checksum != Checksum)
                    {
                        _callbacks.OnLogState?.Invoke($"Original f{_sync.FrameCount}:", (IntPtr)info.Buffer, info.Size);
                        _callbacks.OnLogState?.Invoke($"Replay   f{_sync.FrameCount}:", (IntPtr)_sync.GetLastSavedFrame().Buffer,
                                                      _sync.GetLastSavedFrame().Size);
                        Debug.LogWarning($"SyncTest: Checksum for frame {frame} does not match saved ({Checksum} != {Checksum})");
                    }
                    else
                    {
                        Debug.Log($"Checksum {Checksum} for frame {info.Frame} matches.");
                    }
                    UnsafeUtility.Free(info.Buffer, Allocator.Temp);
                }
                _last_verified = frame;
                _rollingback   = false;
            }
        }
コード例 #7
0
 public void Execute()
 {
     UnsafeUtility.Free(Container.m_Buffer, Container.m_AllocatorLabel);
     Container.m_Buffer = null;
 }
コード例 #8
0
        protected override unsafe void OnUpdate()
        {
            var ecb = new EntityCommandBuffer(Allocator.TempJob);

            Entities
            .WithAll <SceneData, RequestSceneLoaded>()
            .WithNone <SceneLoadRequest>()
            .ForEach((Entity e) =>
            {
                var sceneData = EntityManager.GetComponentData <SceneData>(e);
                var sceneGuid = sceneData.Scene.SceneGuid;
                var path      = DataRootPath + sceneGuid.Guid.ToString("N");
#if IO_ENABLE_TRACE
                Debug.Log($"SceneStreamingSystem: starting load for {DebugSceneGuid(sceneData)} from {path}");
#endif

                // Fire async reads for scene data
                SceneLoadRequest request = new SceneLoadRequest();
                request.SceneOpHandle    = IOService.RequestAsyncRead(path);
                ecb.AddComponent(e, request);
                ecb.RemoveComponent <RequestSceneLoaded>(e);

                sceneData.Status = SceneStatus.Loading;
                ecb.SetComponent(e, sceneData);
            });
            ecb.Playback(EntityManager);
            ecb.Dispose();

            var pendingRequests = m_PendingRequestsQuery.ToEntityArray(Allocator.TempJob);
            ecb = new EntityCommandBuffer(Allocator.TempJob);
            foreach (var requestEntity in pendingRequests)
            {
                SceneData        sceneData = EntityManager.GetComponentData <SceneData>(requestEntity);
                SceneLoadRequest request   = EntityManager.GetComponentData <SceneLoadRequest>(requestEntity);

                var opStatus = request.SceneOpHandle.GetStatus();

                if (opStatus <= Status.InProgress)
                {
                    continue;
                }

                if (opStatus == Status.Failure)
                {
                    request.SceneOpHandle.Dispose();
                    ecb.RemoveComponent <SceneLoadRequest>(requestEntity);

                    Debug.Log($"SceneStreamingSystem: Failed to load {DebugSceneGuid(sceneData)}");

                    sceneData.Status = SceneStatus.FailedToLoad;
                    ecb.SetComponent(requestEntity, sceneData);
                    continue;
                }
                Assert.IsTrue(opStatus == Status.Success);

                request.SceneOpHandle.GetData(out var data, out var sceneDataSize);
                SceneHeader header     = *(SceneHeader *)data;
                int         headerSize = UnsafeUtility.SizeOf <SceneHeader>();
                if (header.Version != SceneHeader.CurrentVersion)
                {
                    throw new Exception($"Scene serialization version mismatch in {DebugSceneGuid(sceneData)}. Reading version '{header.Version}', expected '{SceneHeader.CurrentVersion}'");
                }

                byte *decompressedScene = data + headerSize;
                if (header.Codec != Codec.Codec.None)
                {
                    decompressedScene = (byte *)UnsafeUtility.Malloc(header.DecompressedSize, 16, Allocator.Temp);

                    if (!CodecService.Decompress(header.Codec, data + headerSize, sceneDataSize - headerSize, decompressedScene, header.DecompressedSize))
                    {
                        throw new Exception($"Failed to decompress compressed scene {DebugSceneGuid(sceneData)} using codec '{header.Codec}'");
                    }
                }

                using (var sceneReader = new MemoryBinaryReader(decompressedScene))
                {
                    var loadingEM   = m_LoadingWorld.EntityManager;
                    var transaction = loadingEM.BeginExclusiveEntityTransaction();
                    SerializeUtility.DeserializeWorld(transaction, sceneReader);
                    loadingEM.EndExclusiveEntityTransaction();
                }

                var scene    = sceneData.Scene;
                var activeEM = EntityManager;
                activeEM.MoveEntitiesFrom(out var movedEntities, m_LoadingWorld.EntityManager);
                foreach (var e in movedEntities)
                {
                    ecb.AddSharedComponent(e, scene.SceneGuid);
                    ecb.AddSharedComponent(e, scene.SceneInstanceId);
                }

                // Fixup Entity references now that the entities have moved
                EntityManager.World.GetExistingSystem <EntityReferenceRemapSystem>().Update();
                EntityManager.World.GetExistingSystem <RemoveRemapInformationSystem>().Update();

                if (header.Codec != Codec.Codec.None)
                {
                    UnsafeUtility.Free(decompressedScene, Allocator.Temp);
                }
#if IO_ENABLE_TRACE
                Debug.Log($"SceneStreamingSystem: Loaded scene {DebugSceneGuid(sceneData)}");
#endif
                sceneData.Status = SceneStatus.Loaded;
                ecb.SetComponent(requestEntity, sceneData);

                request.SceneOpHandle.Dispose();
                ecb.RemoveComponent <SceneLoadRequest>(requestEntity);

                m_LoadingWorld.EntityManager.PrepareForDeserialize();
                movedEntities.Dispose();
            }
            ecb.Playback(EntityManager);
            ecb.Dispose();
            pendingRequests.Dispose();
        }
コード例 #9
0
            public void Execute()
            {
                var addedSharedComponentsCount   = 0;
                var removedSharedComponentsCount = 0;
                var removedEntityCurrentCount    = 0;
                var addedEntityCurrentCount      = 0;

                for (var i = 0; i < RemovedShadowChunks.Length; i++)
                {
                    var chunkSequenceNumber = RemovedShadowChunks[i];
                    var shadowChunk         = ShadowChunksBySequenceNumber[chunkSequenceNumber];

                    UnsafeUtility.MemCpy((Entity *)RemovedEntities.GetUnsafePtr() + removedEntityCurrentCount, shadowChunk.EntityDataBuffer, shadowChunk.EntityCount * sizeof(Entity));
                    UnsafeUtility.MemCpyReplicate((int *)RemovedEntitiesMappingToComponent.GetUnsafePtr() + removedEntityCurrentCount, &removedSharedComponentsCount, sizeof(int), shadowChunk.EntityCount);
                    removedEntityCurrentCount += shadowChunk.EntityCount;

                    IndicesInManagedComponentStore[removedSharedComponentsCount++] = SharedComponentValueIndexByChunk[chunkSequenceNumber];

                    ShadowChunksBySequenceNumber.Remove(chunkSequenceNumber);
                    SharedComponentValueIndexByChunk.Remove(chunkSequenceNumber);
                    UnsafeUtility.Free(shadowChunk.EntityDataBuffer, Allocator.Persistent);
                }

                for (var i = 0; i < GatheredChanges.Length; i++)
                {
                    var changes = GatheredChanges[i];
                    if (changes.RemovedEntities.Length == 0)
                    {
                        continue;
                    }

                    UnsafeUtility.MemCpy((Entity *)RemovedEntities.GetUnsafePtr() + removedEntityCurrentCount, changes.RemovedEntities.Ptr, changes.RemovedEntities.Length * sizeof(Entity));
                    UnsafeUtility.MemCpyReplicate((int *)RemovedEntitiesMappingToComponent.GetUnsafePtr() + removedEntityCurrentCount, &removedSharedComponentsCount, sizeof(int), changes.RemovedEntities.Length);
                    removedEntityCurrentCount += changes.RemovedEntities.Length;

                    IndicesInManagedComponentStore[removedSharedComponentsCount++] = SharedComponentValueIndexByChunk[changes.Chunk->SequenceNumber];
                }

                for (var i = 0; i < GatheredChanges.Length; i++)
                {
                    var changes = GatheredChanges[i];
                    if (changes.AddedEntities.Length == 0)
                    {
                        continue;
                    }

                    var chunkSequenceNumber = changes.Chunk->SequenceNumber;

                    if (changes.AddedEntities.Length > 0)
                    {
                        var archetype                 = changes.Chunk->Archetype;
                        var indexInTypeArray          = ChunkDataUtility.GetIndexInTypeArray(archetype, TypeIndex);
                        var sharedComponentValueArray = changes.Chunk->SharedComponentValues;
                        var sharedComponentOffset     = indexInTypeArray - archetype->FirstSharedComponent;
                        var sharedComponentDataIndex  = sharedComponentValueArray[sharedComponentOffset];

                        SharedComponentValueIndexByChunk[chunkSequenceNumber] = sharedComponentDataIndex;

                        UnsafeUtility.MemCpy((Entity *)AddedEntities.GetUnsafePtr() + addedEntityCurrentCount, changes.AddedEntities.Ptr, changes.AddedEntities.Length * sizeof(Entity));
                        var index = removedSharedComponentsCount + addedSharedComponentsCount;
                        UnsafeUtility.MemCpyReplicate((int *)AddedEntitiesMappingToComponent.GetUnsafePtr() + addedEntityCurrentCount, &index, sizeof(int), changes.AddedEntities.Length);
                        addedEntityCurrentCount += changes.AddedEntities.Length;

                        IndicesInManagedComponentStore[index] = sharedComponentDataIndex;
                        addedSharedComponentsCount++;
                    }
                }
            }
コード例 #10
0
 public void Dispose()
 {
     UnsafeUtility.Free(m_Counter, m_AllocatorLabel);
     m_Counter = null;
 }
コード例 #11
0
ファイル: KnnJobs.cs プロジェクト: HilariousCow/Goo2Prototype
 public void Dispose()
 {
     UnsafeUtility.Free(m_indices, m_allocator);
 }
コード例 #12
0
 public void Dispose()
 {
     // Free the allocated memory
     UnsafeUtility.Free(m_Buffer, m_AllocatorLabel);
 }
コード例 #13
0
 public void Dispose()
 {
     UnsafeUtility.Free(v1, Allocator.Persistent);
     UnsafeUtility.Free(v2, Allocator.Persistent);
     UnsafeUtility.Free(result, Allocator.Persistent);
 }
コード例 #14
0
ファイル: Deque.cs プロジェクト: dotsnav/dotsnav
 public void Dispose()
 {
     UnsafeUtility.Free(Data, Allocator);
     UnsafeUtility.Free(_control, Allocator);
 }
コード例 #15
0
        public static unsafe void SerializeWorld(EntityManager entityManager, BinaryWriter writer, out int[] sharedComponentsToSerialize, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapInfos)
        {
            writer.Write(CurrentFileFormatVersion);
            var entityComponentStore = entityManager.EntityComponentStore;

            NativeHashMap <EntityArchetype, int> archetypeToIndex;

            EntityArchetype[] archetypeArray;
            GetAllArchetypes(entityComponentStore, out archetypeToIndex, out archetypeArray);

            var typeHashes = new NativeHashMap <ulong, int>(1024, Allocator.Temp);

            foreach (var archetype in archetypeArray)
            {
                for (int iType = 0; iType < archetype.Archetype->TypesCount; ++iType)
                {
                    var typeIndex = archetype.Archetype->Types[iType].TypeIndex;
                    var typeInfo  = TypeManager.GetTypeInfo(typeIndex);
                    var hash      = typeInfo.StableTypeHash;
                    ValidateTypeForSerialization(typeInfo);
                    typeHashes.TryAdd(hash, 0);
                }
            }
            var typeHashSet = typeHashes.GetKeyArray(Allocator.Temp);

            writer.Write(typeHashSet.Length);
            foreach (ulong hash in typeHashSet)
            {
                writer.Write(hash);
            }

            var typeHashToIndexMap = new NativeHashMap <ulong, int>(typeHashSet.Length, Allocator.Temp);

            for (int i = 0; i < typeHashes.Length; ++i)
            {
                typeHashToIndexMap.TryAdd(typeHashSet[i], i);
            }

            WriteArchetypes(writer, archetypeArray, typeHashToIndexMap);
            var sharedComponentMapping = GatherSharedComponents(archetypeArray, out var sharedComponentArraysTotalCount);
            var sharedComponentArrays  = new NativeArray <int>(sharedComponentArraysTotalCount, Allocator.Temp);

            FillSharedComponentArrays(sharedComponentArrays, archetypeArray, sharedComponentMapping);
            writer.Write(sharedComponentArrays.Length);
            writer.WriteArray(sharedComponentArrays);
            sharedComponentArrays.Dispose();

            //TODO: ensure chunks are defragged?

            var bufferPatches   = new NativeList <BufferPatchRecord>(128, Allocator.Temp);
            var totalChunkCount = GenerateRemapInfo(entityManager, archetypeArray, entityRemapInfos);

            writer.Write(totalChunkCount);

            GatherAllUsedBlobAssets(archetypeArray, out var blobAssetRefs, out var blobAssets);

            var blobAssetOffsets   = new NativeArray <int>(blobAssets.Length, Allocator.Temp);
            int totalBlobAssetSize = 0;

            int Align16(int x) => (x + 15) & ~15;

            for (int i = 0; i < blobAssets.Length; ++i)
            {
                totalBlobAssetSize += sizeof(BlobAssetHeader);
                blobAssetOffsets[i] = totalBlobAssetSize;
                totalBlobAssetSize += Align16(blobAssets[i].header->Length);
            }

            writer.Write(totalBlobAssetSize);

            var zeroBytes = int4.zero;

            for (int i = 0; i < blobAssets.Length; ++i)
            {
                var             blobAssetLength = blobAssets[i].header->Length;
                BlobAssetHeader header          = new BlobAssetHeader
                {
                    ValidationPtr = null, Allocator = Allocator.None, Length = Align16(blobAssetLength)
                };
                writer.WriteBytes(&header, sizeof(BlobAssetHeader));
                writer.WriteBytes(blobAssets[i].header + 1, blobAssetLength);
                writer.WriteBytes(&zeroBytes, header.Length - blobAssetLength);
            }

            var tempChunk = (Chunk *)UnsafeUtility.Malloc(Chunk.kChunkSize, 16, Allocator.Temp);

            for (int archetypeIndex = 0; archetypeIndex < archetypeArray.Length; ++archetypeIndex)
            {
                var archetype = archetypeArray[archetypeIndex].Archetype;
                for (var ci = 0; ci < archetype->Chunks.Count; ++ci)
                {
                    var chunk = archetype->Chunks.p[ci];
                    bufferPatches.Clear();

                    UnsafeUtility.MemCpy(tempChunk, chunk, Chunk.kChunkSize);
                    tempChunk->metaChunkEntity = EntityRemapUtility.RemapEntity(ref entityRemapInfos, tempChunk->metaChunkEntity);

                    // Prevent patching from touching buffers allocated memory
                    BufferHeader.PatchAfterCloningChunk(tempChunk);

                    byte *tempChunkBuffer = tempChunk->Buffer;
                    EntityRemapUtility.PatchEntities(archetype->ScalarEntityPatches, archetype->ScalarEntityPatchCount, archetype->BufferEntityPatches, archetype->BufferEntityPatchCount, tempChunkBuffer, tempChunk->Count, ref entityRemapInfos);
                    if (archetype->ContainsBlobAssetRefs)
                    {
                        PatchBlobAssetsInChunkBeforeSave(tempChunk, chunk, blobAssetOffsets, blobAssetRefs);
                    }

                    FillPatchRecordsForChunk(chunk, bufferPatches);

                    ClearChunkHeaderComponents(tempChunk);
                    ChunkDataUtility.MemsetUnusedChunkData(tempChunk, 0);
                    tempChunk->Archetype = (Archetype *)archetypeIndex;

                    if (archetype->NumManagedArrays != 0)
                    {
                        throw new ArgumentException("Serialization of GameObject components is not supported for pure entity scenes");
                    }

                    writer.WriteBytes(tempChunk, Chunk.kChunkSize);

                    writer.Write(bufferPatches.Length);

                    if (bufferPatches.Length > 0)
                    {
                        writer.WriteList(bufferPatches);

                        // Write heap backed data for each required patch.
                        // TODO: PERF: Investigate static-only deserialization could manage one block and mark in pointers somehow that they are not indiviual
                        for (int i = 0; i < bufferPatches.Length; ++i)
                        {
                            var patch  = bufferPatches[i];
                            var header = (BufferHeader *)OffsetFromPointer(tempChunk->Buffer, patch.ChunkOffset);
                            writer.WriteBytes(header->Pointer, patch.AllocSizeBytes);
                            BufferHeader.Destroy(header);
                        }
                    }
                }
            }

            blobAssetRefs.Dispose();
            blobAssets.Dispose();

            bufferPatches.Dispose();
            UnsafeUtility.Free(tempChunk, Allocator.Temp);

            sharedComponentsToSerialize = new int[sharedComponentMapping.Length - 1];

            using (var keyArray = sharedComponentMapping.GetKeyArray(Allocator.Temp))
                foreach (var key in keyArray)
                {
                    if (key == 0)
                    {
                        continue;
                    }

                    if (sharedComponentMapping.TryGetValue(key, out var val))
                    {
                        sharedComponentsToSerialize[val - 1] = key;
                    }
                }

            archetypeToIndex.Dispose();
            typeHashes.Dispose();
            typeHashSet.Dispose();
            typeHashToIndexMap.Dispose();
        }
コード例 #16
0
    protected unsafe override void Start()
    {
        float3 gravity = new float3(0, -9.81f, 0);

        base.init(gravity);

        // Make heightfield data
        float *heights;
        int2   size;
        float3 scale;
        bool   simple   = false;
        bool   flat     = false;
        bool   mountain = false;

        if (simple)
        {
            size       = new int2(2, 2);
            scale      = new float3(1, 0.1f, 1);
            heights    = (float *)UnsafeUtility.Malloc(size.x * size.y * sizeof(float), 4, Allocator.Temp);
            heights[0] = 1;
            heights[1] = 0;
            heights[2] = 0;
            heights[3] = 1;
        }
        else
        {
            size  = new int2(SizeX, SizeZ);
            scale = new float3(ScaleX, ScaleY, ScaleZ);
            float period = 50.0f;
            heights = (float *)UnsafeUtility.Malloc(size.x * size.y * sizeof(float), 4, Allocator.Temp);
            for (int j = 0; j < size.y; j++)
            {
                for (int i = 0; i < size.x; i++)
                {
                    float a = (i + j) * 2.0f * (float)math.PI / period;
                    heights[i + j * size.x] = flat ? 0.0f : math.sin(a);
                    if (mountain)
                    {
                        float fractionFromCenter = 1.0f - math.min(math.length(new float2(i - size.x / 2, j - size.y / 2)) / (math.min(size.x, size.y) / 2), 1.0f);
                        float mountainHeight     = math.smoothstep(0.0f, 1, fractionFromCenter) * 25.0f;
                        heights[i + j * size.x] += mountainHeight;
                    }
                }
            }
        }

        // static terrain
        Entity staticEntity;
        {
            BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.TerrainCollider.Create(size, scale, heights, Method);

            bool convertToMesh = false;
            if (convertToMesh)
            {
#pragma warning disable 618
                var res = Unity.Physics.Authoring.DisplayBodyColliders.DrawComponent.BuildDebugDisplayMesh((Unity.Physics.Collider *)collider.GetUnsafePtr());
#pragma warning restore 618
                Vector3[] v        = res[0].Mesh.vertices;
                float3[]  vertices = new float3[v.Length];
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i] = v[i];
                }
                collider = Unity.Physics.MeshCollider.Create(vertices, res[0].Mesh.triangles);
            }

            bool compound = false;
            if (compound)
            {
                var instances = new NativeArray <CompoundCollider.ColliderBlobInstance>(4, Allocator.Temp);
                for (int i = 0; i < 4; i++)
                {
                    instances[i] = new CompoundCollider.ColliderBlobInstance
                    {
                        Collider          = collider,
                        CompoundFromChild = new RigidTransform
                        {
                            pos = new float3((i % 2) * scale.x * (size.x - 1), 0.0f, (i / 2) * scale.z * (size.y - 1)),
                            rot = quaternion.identity
                        }
                    };
                }
                collider = Unity.Physics.CompoundCollider.Create(instances);
                instances.Dispose();
            }

            float3 position = new float3(size.x - 1, 0.0f, size.y - 1) * scale * -0.5f;
            staticEntity = CreateStaticBody(position, quaternion.identity, collider);
        }

        UnsafeUtility.Free(heights, Allocator.Temp);
    }
コード例 #17
0
            public unsafe void Execute(ref HitResult thisHitResult, ref Translation translation, ref Rotation rotation, ref VehicleData vehicleData, ref BVHAABB bvhAabb)
            {
                var threadRandom = RdGens[threadId];

                float3 currentPos = translation.Value;
                float3 currentDir = vehicleData.Forward;

                int laneCount, nextLane;

                //spawn new pos
                if (!BoundingBox.Contains(currentPos))
                {
                    int nextSeg = threadRandom.NextInt(0, RoadSegments.Length);

                    float3     nextForward = RoadSegments[nextSeg].Direction;
                    quaternion newRot      = quaternion.LookRotation(nextForward, new float3()
                    {
                        x = 0, y = 1, z = 0
                    });

                    laneCount = RoadSegments[nextSeg].LaneNumber;
                    nextLane  = 0;
                    float laneOffset = (nextLane + 0.5f) * RoadSegments[nextSeg].LaneWidth;
                    if (RoadSegments[nextSeg].IsOneWay == 1)
                    {
                        laneOffset -= (laneCount / 2.0f) * RoadSegments[nextSeg].LaneWidth;
                    }

                    float nextPerct = 0;

                    float3 nextPos = (1.0f - nextPerct) * RoadNodes[RoadSegments[nextSeg].StartNodeId].Position +
                                     (nextPerct) * RoadNodes[RoadSegments[nextSeg].EndNodeId].Position;
                    nextPos += laneOffset * RoadSegments[nextSeg].RightDirection;

                    vehicleData = new VehicleData(
                        vehicleData.Id,
                        nextSeg,
                        vehicleData.Speed,
                        nextForward,
                        nextPerct,
                        1.0f,
                        nextPos,
                        nextLane,
                        50.0f
                        );

                    BVHAABB newAABB = bvhAabb;
                    newAABB.Max += (nextPos - currentPos);
                    newAABB.Min += (nextPos - currentPos);
                    bvhAabb      = newAABB;

                    translation = new Translation()
                    {
                        Value = nextPos
                    };
                    rotation = new Rotation()
                    {
                        Value = newRot
                    };
                    return;
                }

                #region Redlight infront
                int    currentSeg                    = vehicleData.SegId;
                int    nextCrossing                  = vehicleData.Direction > 0.0f ? RoadSegments[currentSeg].EndNodeId : RoadSegments[currentSeg].StartNodeId;
                float3 nextCrossingPos               = RoadNodes[nextCrossing].Position;
                float  distanceToCrossing            = math.distance(currentPos, nextCrossingPos);
                int2   nextCrossingGreenlightConnect =
                    RoadNodes[nextCrossing].ConnectionSegIds[RoadNodes[nextCrossing].ActiveConnection];
                if (currentSeg != nextCrossingGreenlightConnect.x && currentSeg != nextCrossingGreenlightConnect.y &&
                    distanceToCrossing < 20.0f)
                {
                    return;
                }
                #endregion

                #region SpeedVariation
                float prevDistanceAhead = vehicleData.HitDistAhead;
                float newDistanceAhead  = thisHitResult.FrontHitDistance;
                float distAheadDiff     = prevDistanceAhead - newDistanceAhead;
                int   hitResult         = thisHitResult.HitResultPacked;
                float maxSpeed          = RoadSegments[vehicleData.SegId].MaxSpeed;
                float newSpeed          = vehicleData.Speed;
                if (hitResult == 0 && newSpeed < maxSpeed)
                {
                    newSpeed += 0.5f;
                }
                else if ((hitResult & 0x1) == 1 && (distAheadDiff > 0))
                {
                    newSpeed -= ((distAheadDiff) / 20.0f);
                }

                if (newDistanceAhead < 5.0f)
                {
                    newSpeed = 0.0f;
                }

                newSpeed = newSpeed > maxSpeed ? maxSpeed : newSpeed;
                newSpeed = newSpeed < 0 ? 0 : newSpeed;
                #endregion

                float stepLength  = newSpeed * DeltaTime;
                float segLength   = RoadSegments[vehicleData.SegId].Length;
                float stepPerc    = stepLength / segLength;
                float nextPosPerc = vehicleData.CurrentSegPos + stepPerc * vehicleData.Direction;


                #region switchLane

                laneCount = RoadSegments[vehicleData.SegId].LaneNumber;
                int currentLane = vehicleData.Lane;
                int laneSwitch  = threadRandom.NextInt(-10, 10);
                laneSwitch = laneSwitch / 10;
                if (currentLane == 0 && laneSwitch == -1)
                {
                    laneSwitch = 0;
                }
                if (currentLane == (laneCount - 1) && laneSwitch == 1)
                {
                    laneSwitch = 0;
                }
                nextLane = vehicleData.Lane + laneSwitch;
                #endregion

                //great, still in this seg
                if (nextPosPerc < 1.0f && nextPosPerc > 0.0f)
                {
                    //step forward
                    float3 nextPos = currentPos + currentDir * stepLength;
                    //offset lane
                    nextPos += laneSwitch * vehicleData.Direction * RoadSegments[vehicleData.SegId].LaneWidth *
                               RoadSegments[vehicleData.SegId].RightDirection;
                    vehicleData = new VehicleData(
                        vehicleData.Id,
                        vehicleData.SegId,
                        newSpeed,
                        vehicleData.Forward,
                        nextPosPerc,
                        vehicleData.Direction,
                        nextPos,
                        nextLane,
                        newDistanceAhead
                        );

                    BVHAABB newAABB = bvhAabb;
                    newAABB.Max += currentDir * stepLength;
                    newAABB.Min += currentDir * stepLength;
                    bvhAabb      = newAABB;

                    translation = new Translation()
                    {
                        Value = nextPos
                    };
                }
                //reach end node, find next seg
                else
                {
                    //find next available segment
                    int *_availableSeg = (int *)UnsafeUtility.Malloc(
                        5 * sizeof(int), sizeof(int), Allocator.Temp);
                    int availableSegCount = 0;
                    for (int k = 0; k < 3; k++)
                    {
                        int seg1 = RoadNodes[nextCrossing].ConnectionSegIds[k].x;
                        int seg2 = RoadNodes[nextCrossing].ConnectionSegIds[k].y;
                        if (seg1 != -1 && seg1 != currentSeg && //not current seg, and next seg not one-way
                            !(RoadSegments[seg1].EndNodeId == nextCrossing && RoadSegments[seg1].IsOneWay == 1))
                        {
                            _availableSeg[availableSegCount++] = seg1;
                        }
                        if (seg2 != -1 && seg2 != currentSeg && //not current seg, and next seg not one-way
                            !(RoadSegments[seg2].EndNodeId == nextCrossing && RoadSegments[seg2].IsOneWay == 1))
                        {
                            _availableSeg[availableSegCount++] = seg2;
                        }
                    }

                    int   nextSeg = currentSeg;
                    float dir     = 1.0f;
                    if (availableSegCount > 0)//luckily we can proceed
                    {
                        int selectSegId = threadRandom.NextInt(0, availableSegCount);
                        nextSeg = _availableSeg[selectSegId];
                        dir     = RoadSegments[nextSeg].StartNodeId == nextCrossing ? 1.0f : -1.0f;
                    }
                    else//to the end, spawn a new pos
                    {
                        nextSeg = threadRandom.NextInt(0, RoadSegments.Length);
                    }

                    float3     nextForward = RoadSegments[nextSeg].Direction * dir;
                    quaternion newRot      = quaternion.LookRotation(nextForward, new float3()
                    {
                        x = 0, y = 1, z = 0
                    });

                    laneCount = RoadSegments[nextSeg].LaneNumber;
                    nextLane  = nextLane < laneCount ? nextLane : laneCount - 1;
                    float laneOffset = (nextLane + 0.5f) * RoadSegments[nextSeg].LaneWidth;
                    if (RoadSegments[nextSeg].IsOneWay == 1)
                    {
                        laneOffset -= (laneCount / 2.0f) * RoadSegments[nextSeg].LaneWidth;
                    }

                    float nextPerct = dir > 0.0f
                        ? (nextPosPerc > 0.0f ? nextPosPerc - 1.0f : -nextPosPerc)
                        : (nextPosPerc > 0.0f ? 2.0f - nextPosPerc : nextPosPerc + 1.0f);

                    float3 nextPos = (1.0f - nextPerct) * RoadNodes[RoadSegments[nextSeg].StartNodeId].Position +
                                     (nextPerct) * RoadNodes[RoadSegments[nextSeg].EndNodeId].Position;
                    nextPos += laneOffset * dir * RoadSegments[nextSeg].RightDirection;

                    vehicleData = new VehicleData(
                        vehicleData.Id,
                        nextSeg,
                        newSpeed,
                        nextForward,
                        nextPerct,
                        dir,
                        nextPos,
                        nextLane,
                        newDistanceAhead
                        );

                    BVHAABB newAABB = bvhAabb;
                    newAABB.Max += (nextPos - currentPos);
                    newAABB.Min += (nextPos - currentPos);
                    bvhAabb      = newAABB;

                    translation = new Translation()
                    {
                        Value = nextPos
                    };
                    rotation = new Rotation()
                    {
                        Value = newRot
                    };

                    UnsafeUtility.Free(_availableSeg, Allocator.Temp);
                    RdGens[threadId] = threadRandom;
                    _availableSeg    = null;
                }
            }
コード例 #18
0
ファイル: HeapAllocator.cs プロジェクト: pjsheeha/udpgame
 public void Dispose()
 {
     m_Blocks->Dispose();
     UnsafeUtility.Free(m_Blocks, Allocator.Persistent);
 }
コード例 #19
0
 public void Dispose()
 {
     UnsafeUtility.Free(v, Allocator.Persistent);
     UnsafeUtility.Free(gradient, Allocator.Persistent);
 }
コード例 #20
0
 public void Dispose()
 {
     UnsafeUtility.Free(q, Allocator.Persistent);
     UnsafeUtility.Free(rt, Allocator.Persistent);
     UnsafeUtility.Free(pos, Allocator.Persistent);
 }
コード例 #21
0
 public void Execute()
 {
     UnsafeUtility.Free(Ptr, Allocator);
 }
コード例 #22
0
 public void Dispose()
 {
     UnsafeUtility.Free(f4, Allocator.Persistent);
     UnsafeUtility.Free(u4, Allocator.Persistent);
 }
コード例 #23
0
 public void Dispose()
 {
     UnsafeUtility.Free(m_RootPtr, Allocator.Persistent);
 }
 public unsafe void Execute()
 {
     *m_Ptr = 0;
     UnsafeUtility.Free(m_Ptr, m_Allocator);
 }
コード例 #25
0
 public void Execute()
 {
     OutputStreamContext->End();
     UnsafeUtility.Free(OutputStreamContext, Allocator.TempJob);
 }
コード例 #26
0
        // Create a compound collider containing an array of other colliders.
        // The source colliders are copied into the compound, so that it becomes one blob.
        public static unsafe BlobAssetReference <Collider> Create(NativeArray <ColliderBlobInstance> children)
        {
            SafetyChecks.CheckNotEmptyAndThrow(children, nameof(children));

            // Get the total required memory size for the compound plus all its children,
            // and the combined filter of all children
            // TODO: Verify that the size is enough
            int             totalSize = Math.NextMultipleOf16(UnsafeUtility.SizeOf <CompoundCollider>());
            CollisionFilter filter    = children[0].Collider.Value.Filter;
            var             srcToDestInstanceAddrs = new NativeHashMap <long, long>(children.Length, Allocator.Temp);

            for (var childIndex = 0; childIndex < children.Length; childIndex++)
            {
                var child       = children[childIndex];
                var instanceKey = (long)child.Collider.GetUnsafePtr();
                if (srcToDestInstanceAddrs.ContainsKey(instanceKey))
                {
                    continue;
                }
                totalSize += Math.NextMultipleOf16(child.Collider.Value.MemorySize);
                filter     = CollisionFilter.CreateUnion(filter, child.Collider.Value.Filter);
                srcToDestInstanceAddrs.Add(instanceKey, 0L);
            }
            totalSize += (children.Length + BoundingVolumeHierarchy.Constants.MaxNumTreeBranches) * UnsafeUtility.SizeOf <BoundingVolumeHierarchy.Node>();

            // Allocate the collider
            var compoundCollider = (CompoundCollider *)UnsafeUtility.Malloc(totalSize, 16, Allocator.Temp);

            UnsafeUtility.MemClear(compoundCollider, totalSize);
            compoundCollider->m_Header.Type          = ColliderType.Compound;
            compoundCollider->m_Header.CollisionType = CollisionType.Composite;
            compoundCollider->m_Header.Version       = 1;
            compoundCollider->m_Header.Magic         = 0xff;
            compoundCollider->m_Header.Filter        = filter;

            // Initialize children array
            Child *childrenPtr = (Child *)((byte *)compoundCollider + UnsafeUtility.SizeOf <CompoundCollider>());

            compoundCollider->m_ChildrenBlob.Offset = (int)((byte *)childrenPtr - (byte *)(&compoundCollider->m_ChildrenBlob.Offset));
            compoundCollider->m_ChildrenBlob.Length = children.Length;
            byte *end = (byte *)childrenPtr + UnsafeUtility.SizeOf <Child>() * children.Length;

            end = (byte *)Math.NextMultipleOf16((ulong)end);

            uint maxTotalNumColliderKeyBits = 0;

            // Copy children
            for (int i = 0; i < children.Length; i++)
            {
                Collider *collider       = (Collider *)children[i].Collider.GetUnsafePtr();
                var       srcInstanceKey = (long)collider;
                var       dstAddr        = srcToDestInstanceAddrs[srcInstanceKey];
                if (dstAddr == 0L)
                {
                    dstAddr = (long)end;
                    srcToDestInstanceAddrs[srcInstanceKey] = dstAddr;
                    UnsafeUtility.MemCpy(end, collider, collider->MemorySize);
                    end += Math.NextMultipleOf16(collider->MemorySize);
                }
                childrenPtr[i].m_ColliderOffset  = (int)((byte *)dstAddr - (byte *)(&childrenPtr[i].m_ColliderOffset));
                childrenPtr[i].CompoundFromChild = children[i].CompoundFromChild;

                maxTotalNumColliderKeyBits = math.max(maxTotalNumColliderKeyBits, collider->TotalNumColliderKeyBits);
            }

            // Build mass properties
            compoundCollider->MassProperties = compoundCollider->BuildMassProperties();

            // Build bounding volume
            int numNodes = compoundCollider->BuildBoundingVolume(out NativeArray <BoundingVolumeHierarchy.Node> nodes);
            int bvhSize  = numNodes * UnsafeUtility.SizeOf <BoundingVolumeHierarchy.Node>();

            compoundCollider->m_BvhNodesBlob.Offset = (int)(end - (byte *)(&compoundCollider->m_BvhNodesBlob.Offset));
            compoundCollider->m_BvhNodesBlob.Length = numNodes;
            UnsafeUtility.MemCpy(end, nodes.GetUnsafeReadOnlyPtr(), bvhSize);
            compoundCollider->UpdateCachedBoundingRadius();
            end += bvhSize;

            // Validate nesting level of composite colliders.
            compoundCollider->TotalNumColliderKeyBits = maxTotalNumColliderKeyBits + compoundCollider->NumColliderKeyBits;

            // If TotalNumColliderKeyBits is greater than 32, it means maximum nesting level of composite colliders has been breached.
            // ColliderKey has 32 bits so it can't handle infinite nesting of composite colliders.
            if (compoundCollider->TotalNumColliderKeyBits > 32)
            {
                SafetyChecks.ThrowArgumentException(nameof(children), "Composite collider exceeded maximum level of nesting!");
            }

            // Copy to blob asset
            int usedSize = (int)(end - (byte *)compoundCollider);

            UnityEngine.Assertions.Assert.IsTrue(usedSize < totalSize);
            compoundCollider->MemorySize = usedSize;
            var blob = BlobAssetReference <Collider> .Create(compoundCollider, usedSize);

            UnsafeUtility.Free(compoundCollider, Allocator.Temp);

            return(blob);
        }
コード例 #27
0
 public void Dispose()
 {
     ReleaseAllUploadBuffers();
     UnsafeUtility.Free(m_ThreadData, Allocator.Persistent);
 }
コード例 #28
0
 public void Dispose()
 {
     UnsafeUtility.Free((void *)data->arrayPtr, Allocator.Persistent);
     UnsafeUtility.Free(data, Allocator.Persistent);
 }
コード例 #29
0
        void InstantiateEntitiesGroup(Entity *srcEntities, int srcEntityCount,
                                      Entity *outputRootEntities, int instanceCount)
        {
            int totalCount = srcEntityCount * instanceCount;

            var tempAllocSize = sizeof(EntityRemapUtility.SparseEntityRemapInfo) * totalCount +
                                sizeof(InstantiateRemapChunk) * totalCount + sizeof(Entity) * instanceCount;
            byte *    allocation;
            const int kMaxStackAllocSize = 16 * 1024;

            if (tempAllocSize > kMaxStackAllocSize)
            {
                allocation = (byte *)UnsafeUtility.Malloc(tempAllocSize, 16, Allocator.Temp);
            }
            else
            {
                var temp = stackalloc byte[tempAllocSize];

                allocation = temp;
            }

            var entityRemap    = (EntityRemapUtility.SparseEntityRemapInfo *)allocation;
            var remapChunks    = (InstantiateRemapChunk *)(entityRemap + totalCount);
            var outputEntities = (Entity *)(remapChunks + totalCount);

            var remapChunksCount = 0;

            for (int i = 0; i != srcEntityCount; i++)
            {
                var srcEntity = srcEntities[i];

                remapChunksCount = InstantiateEntitiesOne(srcEntity,
                                                          outputEntities, instanceCount, remapChunks, remapChunksCount);

                for (int r = 0; r != instanceCount; r++)
                {
                    var ptr = entityRemap + (r * srcEntityCount + i);
                    ptr->Src    = srcEntity;
                    ptr->Target = outputEntities[r];
                }

                if (i == 0)
                {
                    for (int r = 0; r != instanceCount; r++)
                    {
                        outputRootEntities[r] = outputEntities[r];
                    }
                }
            }


            for (int i = 0; i != remapChunksCount; i++)
            {
                var chunk              = remapChunks[i].Chunk;
                var dstArchetype       = chunk->Archetype;
                var allocatedCount     = remapChunks[i].AllocatedCount;
                var indexInChunk       = remapChunks[i].IndexInChunk;
                var instanceBeginIndex = remapChunks[i].InstanceBeginIndex;

                var localRemap = entityRemap + instanceBeginIndex * srcEntityCount;

                EntityRemapUtility.PatchEntitiesForPrefab(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1,
                                                          dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount,
                                                          chunk->Buffer, indexInChunk, allocatedCount, localRemap, srcEntityCount);

                ManagedChangesTracker.PatchEntitiesForPrefab(dstArchetype, chunk, indexInChunk, allocatedCount, localRemap, srcEntityCount, Allocator.Temp);
            }

            if (tempAllocSize > kMaxStackAllocSize)
            {
                UnsafeUtility.Free(allocation, Allocator.Temp);
            }
        }
コード例 #30
0
        /// <summary>
        /// Reallocate to grow the capacity of the set
        /// </summary>
        ///
        /// <param name="newCapacity">
        /// Capacity to grow to. Must be larger than the current capacity.
        /// </param>
        private void Reallocate(int newCapacity)
        {
            int newBucketCapacity = newCapacity * 2;

            newBucketCapacity = NextHigherPowerOfTwo(newBucketCapacity);

            // No change in capacity
            if (m_State->ItemCapacity == newCapacity &&
                m_State->BucketCapacityMask + 1 == newBucketCapacity)
            {
                return;
            }

            // Can't shrink
            if (newCapacity < m_State->ItemCapacity)
            {
                throw new Exception("NativeHashSet<T> can't shrink");
            }

            // Allocate new data
            int nextOffset;
            int bucketOffset;
            int totalSize = CalculateDataLayout(
                newCapacity,
                newBucketCapacity,
                out nextOffset,
                out bucketOffset);
            byte *newData = (byte *)UnsafeUtility.Malloc(
                totalSize,
                JobsUtility.CacheLineSize,
                m_Allocator);
            byte *newItems   = newData;
            byte *newNext    = newData + nextOffset;
            byte *newBuckets = newData + bucketOffset;

            // The items are taken from a free-list and might not be tightly
            // packed, copy all of the old capacity
            UnsafeUtility.MemCpy(
                newItems,
                m_State->Items,
                m_State->ItemCapacity * UnsafeUtility.SizeOf <T>());
            UnsafeUtility.MemCpy(
                newNext,
                m_State->Next,
                m_State->ItemCapacity * UnsafeUtility.SizeOf <int>());
            for (
                int emptyNext = m_State->ItemCapacity;
                emptyNext < newCapacity;
                ++emptyNext)
            {
                ((int *)newNext)[emptyNext] = -1;
            }

            // Re-hash the buckets, first clear the new bucket list, then insert
            // all values from the old list
            for (int bucket = 0; bucket < newBucketCapacity; ++bucket)
            {
                ((int *)newBuckets)[bucket] = -1;
            }
            for (int bucket = 0; bucket <= m_State->BucketCapacityMask; ++bucket)
            {
                int *buckets  = (int *)m_State->Buckets;
                int *nextPtrs = (int *)newNext;
                while (buckets[bucket] >= 0)
                {
                    int curEntry = buckets[bucket];
                    buckets[bucket] = nextPtrs[curEntry];
                    int newBucket = UnsafeUtility.ReadArrayElement <T>(
                        m_State->Items,
                        curEntry).GetHashCode() & (newBucketCapacity - 1);
                    nextPtrs[curEntry]             = ((int *)newBuckets)[newBucket];
                    ((int *)newBuckets)[newBucket] = curEntry;
                }
            }

            // Free the old state contents
            UnsafeUtility.Free(m_State->Items, m_Allocator);

            // Set the new state contents
            if (m_State->AllocatedIndexLength > m_State->ItemCapacity)
            {
                m_State->AllocatedIndexLength = m_State->ItemCapacity;
            }
            m_State->Items              = newData;
            m_State->Next               = newNext;
            m_State->Buckets            = newBuckets;
            m_State->ItemCapacity       = newCapacity;
            m_State->BucketCapacityMask = newBucketCapacity - 1;
        }