public override void UpdateBehaviour() { #if UNITY_EDITOR debugDrawDependencies.Complete(); NativeArray <DebugDrawCommand> debugDrawCommands = m_debugDrawCommandQueue.ToArray(Allocator.Temp); m_debugDrawCommandQueue.Clear(); for (int debugDrawCommandIndex = 0; debugDrawCommandIndex < debugDrawCommands.Length; debugDrawCommandIndex++) { DebugDrawCommand debugDrawCommand = debugDrawCommands[debugDrawCommandIndex]; switch (debugDrawCommand.debugDrawCommandType) { case DebugDrawCommandType.Line: DebugDrawLineData debugDrawLineData = debugDrawCommand.DebugCommandData <DebugDrawLineData>(); Debug.DrawLine(debugDrawLineData.start, debugDrawLineData.end, debugDrawLineData.colour); break; case DebugDrawCommandType.Sphere: break; default: throw new Exception("Invalid debug draw command type"); } } debugDrawCommands.Dispose(); #endif }
public unsafe void Test() { const int cnt = 1000; using var queue = new NativeQueue <int>(0); var managed = new Queue <int>(cnt); var arr = new int[cnt]; var rand = new Random(); for (int i = 0; i < cnt; i++) { arr[i] = rand.Next(cnt); } for (int i = 0; i < cnt; i++) { managed.Enqueue(arr[i]); queue.Enqueue(arr[i]); } var se = queue.GetEnumerator(); var me = managed.GetEnumerator(); var toArr = queue.ToArray(); for (var i = 0; i < cnt; i++) { se.MoveNext(); me.MoveNext(); Assert.True(se.Current == me.Current); Assert.True(toArr[i] == se.Current); } se.Dispose(); me.Dispose(); for (int i = 0; i < cnt; i++) { Assert.True(managed.Count == queue.Count); var l = managed.Dequeue(); var r = queue.Peek(); Assert.True(l == r); queue.Dequeue(); } queue.Clear(); queue.TrimExcess(); Assert.True(!queue.IsDisposed); queue.Dispose(); Assert.True(queue.Ptr == null); Assert.True(queue.IsDisposed); }
protected override void OnUpdate() { EntityQuery enemyQuery = GetEntityQuery(typeof(EnemyComponent), typeof(Translation)); EntityQuery playerQuery = GetEntityQuery(typeof(PlayerComponent), typeof(Translation)); NativeArray <Entity> enemies = enemyQuery.ToEntityArray(Allocator.TempJob); NativeArray <Translation> enemyTrans = enemyQuery.ToComponentDataArray <Translation>(Allocator.TempJob); NativeArray <CollisionData> enemyCollisionDatas = new NativeArray <CollisionData>(enemies.Length, Allocator.TempJob); for (int i = 0; i < enemies.Length; i++) { CollisionData data = new CollisionData(); data.entity = enemies[i]; data.position = enemyTrans[i].Value; data.radius = GameSetting.Instance.enemyRadius + GameSetting.Instance.playerRadius; enemyCollisionDatas[i] = data; } enemies.Dispose(); enemyTrans.Dispose(); NativeQueue <Entity> collisionEnemies = new NativeQueue <Entity>(Allocator.TempJob); CollisionDetectJob job = new CollisionDetectJob() { collisionDatas = enemyCollisionDatas, translationType = GetArchetypeChunkComponentType <Translation>(), entityType = GetArchetypeChunkEntityType(), collisionEntity = collisionEnemies.AsParallelWriter(), }; JobHandle handle = job.Schedule(playerQuery); handle.Complete(); if (collisionEnemies.Count > 0) { NativeArray <Entity> removeEntity = collisionEnemies.ToArray(Allocator.Temp); this.EntityManager.DestroyEntity(removeEntity); //foreach (var item in removeEntity) //{ // Debug.LogFormat("remove count:{0},index:{1},version:{2}" , removeEntity.Length,item.Index,item.Version); //} removeEntity.Dispose(); } collisionEnemies.Dispose(); enemyCollisionDatas.Dispose(); }
public void ToArray_WorksFromJobs() { using (var queue = new NativeQueue <int>(Allocator.TempJob)) { new EnqueueJob { Queue = queue.AsParallelWriter() }.Schedule(100, 10).Complete(); Assert.AreEqual(100, queue.Count); using (var arr = queue.ToArray(Allocator.Temp)) { Assert.AreEqual(100, arr.Length); arr.Sort(); for (int i = 0; i < arr.Length; i++) { Assert.AreEqual(i, arr[i]); } } } }
//protected override void OnUpdate() //{ // matrices.Clear(); // block.Clear(); // EntityQuery entityQuery = GetEntityQuery(typeof(Translation), typeof(EnemyComponent)); // NativeArray<Translation> nativeArray = entityQuery.ToComponentDataArray<Translation>(Allocator.Temp); // for (int i = 0; i < nativeArray.Length; i++) // { // for (int j = i; j < nativeArray.Length - 1; j++) // { // if (nativeArray[j].Value.y < nativeArray[j + 1].Value.y) // { // Translation temp = nativeArray[j]; // nativeArray[j] = nativeArray[j + 1]; // nativeArray[j + 1] = temp; // } // } // } // foreach (var item in nativeArray) // { // matrices.Add(Matrix4x4.TRS(item.Value, Quaternion.identity, Vector3.one)); // if (matrices.Count >= 1023) // { // Graphics.DrawMeshInstanced(GameSetting.Instance.entityMesh, 0, GameSetting.Instance.enemyMat, matrices, block); // matrices.Clear(); // } // } // Graphics.DrawMeshInstanced(GameSetting.Instance.entityMesh, 0, GameSetting.Instance.enemyMat, matrices, block); // EntityQueryBuilder queryBuilder = Entities.WithNone(typeof(EnemyComponent)).WithAll(typeof(Translation)); // queryBuilder.ForEach((ref Translation translation, ref Rotation rotation) => // { // Graphics.DrawMesh(GameSetting.Instance.entityMesh, translation.Value, rotation.Value, GameSetting.Instance.playerMat, LayerMask.GetMask("Default")); // }); //} protected override void OnUpdate() { matrices.Clear(); block.Clear(); int jobHandleindex = 0; NativeArray <JobHandle> jobHandles = new NativeArray <JobHandle>(4, Allocator.Temp); EntityQuery entityQuery = GetEntityQuery(typeof(Translation), typeof(EnemyComponent)); NativeQueue <RenderData> renderQueue0 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> renderQueue1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> renderQueue2 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> renderQueue3 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <Entity> toRemoveEntity = new NativeQueue <Entity>(Allocator.TempJob); Camera camera = Camera.main; NativeQueue <RenderData> .ParallelWriter pw0 = renderQueue0.AsParallelWriter(); NativeQueue <RenderData> .ParallelWriter pw1 = renderQueue1.AsParallelWriter(); NativeQueue <RenderData> .ParallelWriter pw2 = renderQueue2.AsParallelWriter(); NativeQueue <RenderData> .ParallelWriter pw3 = renderQueue3.AsParallelWriter(); NativeQueue <Entity> .ParallelWriter tre = toRemoveEntity.AsParallelWriter(); float halfW = camera.orthographicSize / Screen.currentResolution.height * Screen.currentResolution.width; SpriteCullJob cullJob = new SpriteCullJob() { top = camera.transform.position.y + camera.orthographicSize, bottom = camera.transform.position.y - camera.orthographicSize, left = camera.transform.position.x - halfW, right = camera.transform.position.x + halfW, nativeQueue0 = pw0, nativeQueue1 = pw1, nativeQueue2 = pw2, nativeQueue3 = pw3, typeTranslation = GetArchetypeChunkComponentType <Translation>(), entityType = GetArchetypeChunkEntityType(), needRemoveEntity = tre, }; JobHandle handle = cullJob.Schedule(entityQuery); handle.Complete(); NativeArray <JobHandle> switchHandles = new NativeArray <JobHandle>(4, Allocator.TempJob); int switchJobIndex = 0; NativeArray <RenderData> rd0 = new NativeArray <RenderData>(renderQueue0.Count, Allocator.TempJob), rd1 = new NativeArray <RenderData>(renderQueue1.Count, Allocator.TempJob), rd2 = new NativeArray <RenderData>(renderQueue2.Count, Allocator.TempJob), rd3 = new NativeArray <RenderData>(renderQueue3.Count, Allocator.TempJob); NativeQueue2ArrayJob nativeQueue2Array0 = new NativeQueue2ArrayJob() { nativeQueue = renderQueue0, nativeArray = rd0 }; switchHandles[switchJobIndex++] = nativeQueue2Array0.Schedule(); NativeQueue2ArrayJob nativeQueue2Array1 = new NativeQueue2ArrayJob() { nativeQueue = renderQueue1, nativeArray = rd1 }; switchHandles[switchJobIndex++] = nativeQueue2Array1.Schedule(); NativeQueue2ArrayJob nativeQueue2Array2 = new NativeQueue2ArrayJob() { nativeQueue = renderQueue2, nativeArray = rd2 }; switchHandles[switchJobIndex++] = nativeQueue2Array2.Schedule(); NativeQueue2ArrayJob nativeQueue2Array3 = new NativeQueue2ArrayJob() { nativeQueue = renderQueue3, nativeArray = rd3 }; switchHandles[switchJobIndex++] = nativeQueue2Array3.Schedule(); JobHandle.CompleteAll(switchHandles); switchHandles.Dispose(); renderQueue0.Dispose(); renderQueue1.Dispose(); renderQueue2.Dispose(); renderQueue3.Dispose(); SpriteSortJobs sortJobs0 = new SpriteSortJobs() { renderDatas = rd0, }; jobHandles[jobHandleindex++] = sortJobs0.Schedule(); SpriteSortJobs sortJobs1 = new SpriteSortJobs() { renderDatas = rd1, }; jobHandles[jobHandleindex++] = sortJobs1.Schedule(); SpriteSortJobs sortJobs2 = new SpriteSortJobs() { renderDatas = rd2, }; jobHandles[jobHandleindex++] = sortJobs2.Schedule(); SpriteSortJobs sortJobs3 = new SpriteSortJobs() { renderDatas = rd3, }; jobHandles[jobHandleindex++] = sortJobs3.Schedule(); JobHandle.CompleteAll(jobHandles); foreach (var item in rd0) { AddData(item); } foreach (var item in rd1) { AddData(item); } foreach (var item in rd2) { AddData(item); } foreach (var item in rd3) { AddData(item); } if (matrices.Count > 0) { Graphics.DrawMeshInstanced(GameSetting.Instance.entityMesh, 0, GameSetting.Instance.enemyMat, matrices, block); } rd0.Dispose(); rd1.Dispose(); rd2.Dispose(); rd3.Dispose(); jobHandles.Dispose(); if (toRemoveEntity.Count > 0) { NativeArray <Entity> toRemoveEntityArray = toRemoveEntity.ToArray(Allocator.Temp); this.EntityManager.DestroyEntity(toRemoveEntityArray); toRemoveEntityArray.Dispose(); } toRemoveEntity.Dispose(); Entities.ForEach((ref PlayerComponent playerComponent, ref Translation translation, ref Rotation rotation) => { Graphics.DrawMesh(GameSetting.Instance.entityMesh, translation.Value, rotation.Value, GameSetting.Instance.playerMat, LayerMask.GetMask("Default")); }); }
public void Execute() { var commandQueueArray = commandQueue.ToArray(Allocator.Temp); { // Mass destroy weaponToDestroyCache.Clear(); for (int i = 0; i < commandQueueArray.Length; ++i) { var command = commandQueueArray[i]; if (command.currentWeaponRef.Value != Entity.Null) { weaponToDestroyCache.Add(command.currentWeaponRef.Value); } } if (weaponToDestroyCache.Length > 0) { // To be replaced with batched ECB destroy when API ships { for (int i = 0; i < weaponToDestroyCache.Length; ++i) { commandBuffer.DestroyEntity(weaponToDestroyCache[i]); } } } // Instantiate has to 1-1 since mass instantiate does not work with LinkedEntityGroup newWeaponInstantiatedCache.Clear(); for (int i = 0; i < commandQueueArray.Length; ++i) { var command = commandQueueArray[i]; newWeaponInstantiatedCache.Add(commandBuffer.Instantiate(weaponPrefabs[command.newWeaponIdx])); } // Mass add component { // To be replaced with batched ECB add component when API ships { for (int i = 0; i < newWeaponInstantiatedCache.Length; ++i) { commandBuffer.AddComponent <Parent>(newWeaponInstantiatedCache[i]); } for (int i = 0; i < newWeaponInstantiatedCache.Length; ++i) { commandBuffer.AddComponent <LocalToParent>(newWeaponInstantiatedCache[i]); } } } // There is no mass set component but setting component is way less of a cost than add component for (int i = 0; i < newWeaponInstantiatedCache.Length; ++i) { var command = commandQueueArray[i]; var newWeapon = newWeaponInstantiatedCache[i]; commandBuffer.SetComponent(newWeapon, new Parent { Value = command.weaponOwner }); commandBuffer.SetComponent(newWeapon, new LocalToParent { Value = command.localToParent }); commandBuffer.SetComponent(command.weaponOwner, new Weapon { Value = newWeapon }); } } commandQueueArray.Dispose(); commandQueue.Clear(); }
protected override void OnUpdate() { EntityQuery entityQuery = GetEntityQuery(typeof(Translation), typeof(SpriteSheetComponentData)); NativeArray <SpriteSheetComponentData> animationDataQuery = entityQuery.ToComponentDataArray <SpriteSheetComponentData>(Allocator.TempJob); NativeArray <Translation> translationArray = entityQuery.ToComponentDataArray <Translation>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_2 = new NativeQueue <RenderData>(Allocator.TempJob); Camera cameraMain = Camera.main; float3 cameraPosition = cameraMain.transform.position; float yBottom = cameraPosition.y - cameraMain.orthographicSize; float yTop_1 = cameraPosition.y + cameraMain.orthographicSize; float yTop_2 = cameraPosition.y + 0f; CullAndSortJob cullAndSortJob = new CullAndSortJob { yBottom = yBottom, yTop_1 = yTop_1, yTop_2 = yTop_2, nativeQueue1 = nativeQueue_1.AsParallelWriter(), nativeQueue2 = nativeQueue_2.AsParallelWriter() }; JobHandle jobHandle = cullAndSortJob.Schedule(this); jobHandle.Complete(); animationDataQuery.Dispose(); translationArray.Dispose(); NativeArray <RenderData> nativeArray_1 = nativeQueue_1.ToArray(Allocator.TempJob); NativeArray <RenderData> nativeArray_2 = nativeQueue_2.ToArray(Allocator.TempJob); nativeQueue_1.Dispose(); nativeQueue_2.Dispose(); NativeArray <JobHandle> jobHandleArray = new NativeArray <JobHandle>(2, Allocator.TempJob); SortByPositionJob sortByPositionJob_1 = new SortByPositionJob { dataArray = nativeArray_1 }; jobHandleArray[0] = sortByPositionJob_1.Schedule(); SortByPositionJob sortByPositionJob_2 = new SortByPositionJob { dataArray = nativeArray_2 }; jobHandleArray[1] = sortByPositionJob_2.Schedule(); JobHandle.CompleteAll(jobHandleArray); int visibleEntityTotal = nativeArray_1.Length + nativeArray_2.Length; NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntityTotal, Allocator.TempJob); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntityTotal, Allocator.TempJob); FillArraysParrallelJob fillArraysParrallelJob_1 = new FillArraysParrallelJob { nativeArray = nativeArray_1, matrixArray = matrixArray, uvArray = uvArray, startingIndex = 0 }; jobHandleArray[0] = fillArraysParrallelJob_1.Schedule(nativeArray_1.Length, 10); FillArraysParrallelJob fillArraysParrallelJob_2 = new FillArraysParrallelJob { nativeArray = nativeArray_2, matrixArray = matrixArray, uvArray = uvArray, startingIndex = nativeArray_1.Length }; jobHandleArray[1] = fillArraysParrallelJob_2.Schedule(nativeArray_2.Length, 10); JobHandle.CompleteAll(jobHandleArray); nativeArray_1.Dispose(); nativeArray_2.Dispose(); MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); Vector4[] uv = new Vector4[1]; Mesh quadMesh = GameEntity.GetInstance().quadMesh; Material material = GameEntity.GetInstance().walkingSpriteSheetMaterial; int shaderPropertyId = Shader.PropertyToID("_MainTex_UV"); int sliceCount = 1023; Matrix4x4[] matrixInstancedArray = new Matrix4x4[sliceCount]; Vector4[] uvInstancedArray = new Vector4[sliceCount]; for (int i = 0; i < matrixArray.Length; i += sliceCount) { int sliceSize = Mathf.Min(sliceCount, matrixArray.Length - i); NativeArray <Matrix4x4> .Copy(matrixArray, i, matrixInstancedArray, 0, sliceSize); NativeArray <Vector4> .Copy(uvArray, i, uvInstancedArray, 0, sliceSize); materialPropertyBlock.SetVectorArray(shaderPropertyId, uvInstancedArray); Graphics.DrawMeshInstanced( quadMesh, 0, material, matrixInstancedArray, sliceSize, materialPropertyBlock ); } matrixArray.Dispose(); uvArray.Dispose(); jobHandleArray.Dispose(); }
public void Execute() { *EntityCount += Queue.Count; List.AddRange(Queue.ToArray(Allocator.Temp)); }
protected override void OnUpdate() { // Some initialization must happen on first update for singleton entity query to work if (!initialized) { initialized = true; var weaponDataEntity = GetSingletonEntity <WeaponDataEntry>(); var weaponDatabase = EntityManager.GetBuffer <WeaponDataEntry>(weaponDataEntity); weaponPrefabs.Clear(); for (int i = 0; i < weaponDatabase.Length; ++i) { weaponPrefabs.Add(weaponDatabase[i].prefab); } } commandQueueDependency.Complete(); using (var commandQueueArray = commandQueue.ToArray(Allocator.Temp)) { // Mass destroy weaponToDestroyCache.Clear(); for (int i = 0; i < commandQueueArray.Length; ++i) { var command = commandQueueArray[i]; if (command.currentWeaponRef.Value != Entity.Null) { weaponToDestroyCache.Add(command.currentWeaponRef.Value); } } if (weaponToDestroyCache.Length > 0) { EntityManager.DestroyEntity(weaponToDestroyCache); } // Instantiate has to 1-1 since mass instantiate does not work with LinkedEntityGroup newWeaponInstantiatedCache.Clear(); for (int i = 0; i < commandQueueArray.Length; ++i) { var command = commandQueueArray[i]; newWeaponInstantiatedCache.Add(EntityManager.Instantiate(weaponPrefabs[command.newWeaponIdx])); } // Mass add component EntityManager.AddComponent <Parent>(newWeaponInstantiatedCache); EntityManager.AddComponent <LocalToParent>(newWeaponInstantiatedCache); // There is no mass set component but setting component is way less of a cost than add component for (int i = 0; i < newWeaponInstantiatedCache.Length; ++i) { var command = commandQueueArray[i]; var newWeapon = newWeaponInstantiatedCache[i]; EntityManager.SetComponentData(newWeapon, new Parent { Value = command.weaponOwner }); EntityManager.SetComponentData(newWeapon, new LocalToParent { Value = command.localToParent }); EntityManager.SetComponentData(command.weaponOwner, new Weapon { Value = newWeapon }); } } commandQueue.Clear(); }