protected override void OnUpdate() { EntityQuery query = GetEntityQuery(typeof(SpriteSheetAnimation_Data), typeof(Translation)); NativeArray <SpriteSheetAnimation_Data> animDataArray = query.ToComponentDataArray <SpriteSheetAnimation_Data>(Allocator.TempJob); NativeArray <Translation> translations = query.ToComponentDataArray <Translation>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_2 = new NativeQueue <RenderData>(Allocator.TempJob); Camera camera = Camera.main; float3 cameraPosition = camera.transform.position; float yBottom = cameraPosition.y - camera.orthographicSize; float yTop_1 = cameraPosition.y + camera.orthographicSize; float yTop_2 = cameraPosition.y; CullAndSortJob job = new CullAndSortJob() { yBottom = yBottom, yTop_1 = yTop_1, yTop_2 = yTop_2, nativeQueue_1 = nativeQueue_1.AsParallelWriter(), nativeQueue_2 = nativeQueue_2.AsParallelWriter() }; JobHandle handle = job.Schedule(this); handle.Complete(); NativeArray <RenderData> nativeArray_1 = new NativeArray <RenderData>(nativeQueue_1.Count, Allocator.Temp); NativeArray <RenderData> nativeArray_2 = new NativeArray <RenderData>(nativeQueue_2.Count, Allocator.Temp); NativeQueueToArrayJob queueToArrayJob_1 = new NativeQueueToArrayJob() { array = nativeArray_1, queue = nativeQueue_1 }; NativeQueueToArrayJob queueToArrayJob_2 = new NativeQueueToArrayJob() { array = nativeArray_2, queue = nativeQueue_2 }; NativeArray <JobHandle> handles = new NativeArray <JobHandle>(2, Allocator.Temp); handles[0] = queueToArrayJob_1.Schedule(); handles[1] = queueToArrayJob_2.Schedule(); JobHandle.CompleteAll(handles); nativeQueue_1.Dispose(); nativeQueue_2.Dispose(); SortByPossitionJob sortByPossitionJob_1 = new SortByPossitionJob() { sortArray = nativeArray_1 }; SortByPossitionJob sortByPossitionJob_2 = new SortByPossitionJob() { sortArray = nativeArray_2 }; handles[0] = sortByPossitionJob_1.Schedule(); handles[1] = sortByPossitionJob_2.Schedule(); JobHandle.CompleteAll(handles); int visibleEntities = nativeArray_1.Length + nativeArray_2.Length; NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntities, Allocator.Temp); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntities, Allocator.Temp); Matrix4x4[] matrices = new Matrix4x4[visibleEntities]; Vector4[] uvs = new Vector4[visibleEntities]; FillArraysParallelJob fillArraysJob_1 = new FillArraysParallelJob() { nativeArray = nativeArray_1, matrixArray = matrixArray, uvArray = uvArray, startIndex = 0 }; FillArraysParallelJob fillArraysJob_2 = new FillArraysParallelJob() { nativeArray = nativeArray_2, matrixArray = matrixArray, uvArray = uvArray, startIndex = nativeArray_1.Length }; handles[0] = fillArraysJob_1.Schedule(nativeArray_1.Length, 10); handles[0] = fillArraysJob_2.Schedule(nativeArray_2.Length, 10); JobHandle.CompleteAll(handles); int sliceCount = 1023; for (int i = 0; i < animDataArray.Length; i += sliceCount) { int sliceSize = math.min(animDataArray.Length - i, sliceCount); NativeArray <Matrix4x4> .Copy(matrixArray, i, matrices, 0, sliceSize); NativeArray <Vector4> .Copy(uvArray, i, uvs, 0, sliceSize); propertyBlock.SetVectorArray(shaderPropertyID, uvs); Graphics.DrawMeshInstanced( mesh, 0, material, matrices, sliceSize, propertyBlock ); } matrixArray.Dispose(); uvArray.Dispose(); animDataArray.Dispose(); translations.Dispose(); }
// // // //END OF SPLIT MULTITHREADED CODE /// // // // // // //TODO Basically re-do this code once per different sprite tag, e.g once for User and once for Goblins, then we do 1 draw call per spritesheet protected override void OnUpdate() { //Get our entity reference EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager; EntityQuery entityQuery = GetEntityQuery( typeof(SpriteSheetData)); //TODO Replace spritesheetdata with our tag? or seperate after we have them all by our identifer tags NativeArray <Entity> entitiesToDraw = entityQuery.ToEntityArray(Allocator.TempJob); Entity e = entitiesToDraw[ 0]; //Assume all entities share the shared data here (spritesheet cells, cell size, materials, etc. //Grab other shared data, DynamicBuffer <AnimationClip> animationClips = entityManager.GetBuffer <AnimationClip>(e); MaterialPropertyBlock shaderVariables = new MaterialPropertyBlock(); // //Per different Sprite // SpriteSheetData _spriteSheetData = entityManager.GetComponentData <SpriteSheetData>(e); //Get one per different sprite Vector2 _spriteSheetUVs = _spriteSheetData.GridUVs; MeshData _meshData = entityManager.GetSharedComponentData <MeshData>(e); // // End per different sprite (e.g we can re-use these values for each entity with a tag (.eg goblin) // EntityQuery query = GetEntityQuery(typeof(UniqueAnimationData), typeof(Translation)); NativeArray <UniqueAnimationData> uniqueAnimationDatas = query.ToComponentDataArray <UniqueAnimationData>(Allocator.TempJob); NativeQueue <RenderData> renderQueue1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> renderQueue2 = new NativeQueue <RenderData>(Allocator.TempJob); Camera camera = Camera.main; float3 cameraPos = camera.transform.position; float yBottom = cameraPos.y - camera.orthographicSize; float yTop1 = cameraPos.y + camera.orthographicSize; float yTop2 = cameraPos.y + 0f; CullAndSortJob cullAndSortJob = new CullAndSortJob() { YBottom = yBottom, YTop1 = yTop1, YTop2 = yTop2, nativeQueue_1 = renderQueue1.AsParallelWriter(), nativeQueue_2 = renderQueue2.AsParallelWriter(), spriteSheetUVs = _spriteSheetData.GridUVs }; JobHandle jobHandle = cullAndSortJob.Schedule(this); jobHandle.Complete(); NativeArray <JobHandle> jobHandles = new NativeArray <JobHandle>(2, Allocator.TempJob); NativeArray <RenderData> renderArray1 = new NativeArray <RenderData>(renderQueue1.Count, Allocator.TempJob); NativeArray <RenderData> renderArray2 = new NativeArray <RenderData>(renderQueue2.Count, Allocator.TempJob); RenderQueueToArrayJob renderQueueToArrayJob1 = new RenderQueueToArrayJob() { renderQueue1 = renderQueue1, renderArray = renderArray1 }; RenderQueueToArrayJob renderQueueToArrayJob2 = new RenderQueueToArrayJob() { renderQueue1 = renderQueue2, renderArray = renderArray2 }; jobHandles[0] = renderQueueToArrayJob1.Schedule(); jobHandles[1] = renderQueueToArrayJob2.Schedule(); JobHandle.CompleteAll(jobHandles); renderQueue1.Dispose(); renderQueue2.Dispose(); SortByPositionJob sortByPositionJob1 = new SortByPositionJob() { sortArray = renderArray1 }; SortByPositionJob sortByPositionJob2 = new SortByPositionJob() { sortArray = renderArray2 }; jobHandles[0] = sortByPositionJob1.Schedule(); jobHandles[1] = sortByPositionJob2.Schedule(); JobHandle.CompleteAll(jobHandles); int visibleEntityTotal = renderArray1.Length + renderArray2.Length; NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntityTotal, Allocator.TempJob); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntityTotal, Allocator.TempJob); FillArraysParralelJob fillArraysParralelJob1 = new FillArraysParralelJob() { nativeArray = renderArray1, matrixArray = matrixArray, uvArray = uvArray, startingIndex = 0 }; jobHandles[0] = fillArraysParralelJob1.Schedule(renderArray1.Length, 10); FillArraysParralelJob fillArraysParralelJob2 = new FillArraysParralelJob() { nativeArray = renderArray2, matrixArray = matrixArray, uvArray = uvArray, startingIndex = renderArray1.Length }; jobHandles[1] = fillArraysParralelJob2.Schedule(renderArray2.Length, 10); JobHandle.CompleteAll(jobHandles); int shaderPropertyId = Shader.PropertyToID("_MainTex_UV"); Mesh mesh = MaterialStore.GetInstance().GetMeshById(_meshData.GetMeshID()); int sliceCount = 1023; Matrix4x4[] matrixInstancedArray = new Matrix4x4[sliceCount]; Vector4[] uvInstancedArray = new Vector4[sliceCount]; for (int i = 0; i < uniqueAnimationDatas.Length; i += sliceCount) { int sliceSize = math.min(uniqueAnimationDatas.Length - i, sliceCount); NativeArray <Matrix4x4> .Copy(matrixArray, i, matrixInstancedArray, 0, sliceSize); NativeArray <Vector4> .Copy(uvArray, i, uvInstancedArray, 0, sliceSize); shaderVariables.SetVectorArray(shaderPropertyId, uvInstancedArray); Graphics.DrawMeshInstanced( mesh, 0, _meshData.GetMaterial(), matrixInstancedArray, sliceSize, shaderVariables ); } matrixArray.Dispose(); uvArray.Dispose(); uniqueAnimationDatas.Dispose(); entitiesToDraw.Dispose(); jobHandles.Dispose(); renderArray1.Dispose(); renderArray2.Dispose(); }
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(); }
protected override void OnUpdate() { NativeQueue <RenderData> nativeQueue_1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_2 = new NativeQueue <RenderData>(Allocator.TempJob); Camera camera = Camera.main; float3 cameraPosition = camera.transform.position; float yBottom = cameraPosition.y - camera.orthographicSize; float yTop_1 = cameraPosition.y + camera.orthographicSize; float yTop_2 = cameraPosition.y + 0f; CullAndSortJob cullAndSortJob = new CullAndSortJob { yBottom = yBottom, yTop_1 = yTop_1, yTop_2 = yTop_2, nativeQueue_1 = nativeQueue_1.ToConcurrent(), nativeQueue_2 = nativeQueue_2.ToConcurrent(), }; JobHandle jobHandle = cullAndSortJob.Schedule(this); jobHandle.Complete(); // Convert Queues into Arrays for Sorting NativeArray <RenderData> nativeArray_1 = new NativeArray <RenderData>(nativeQueue_1.Count, Allocator.TempJob); NativeArray <RenderData> nativeArray_2 = new NativeArray <RenderData>(nativeQueue_2.Count, Allocator.TempJob); NativeArray <JobHandle> jobHandleArray = new NativeArray <JobHandle>(2, Allocator.TempJob); NativeQueueToArrayJob nativeQueueToArrayJob_1 = new NativeQueueToArrayJob { nativeQueue = nativeQueue_1, nativeArray = nativeArray_1, }; jobHandleArray[0] = nativeQueueToArrayJob_1.Schedule(); NativeQueueToArrayJob nativeQueueToArrayJob_2 = new NativeQueueToArrayJob { nativeQueue = nativeQueue_2, nativeArray = nativeArray_2, }; jobHandleArray[1] = nativeQueueToArrayJob_2.Schedule(); JobHandle.CompleteAll(jobHandleArray); nativeQueue_1.Dispose(); nativeQueue_2.Dispose(); // Sort arrays by position SortByPositionJob sortByPositionJob_1 = new SortByPositionJob { sortArray = nativeArray_1, }; jobHandleArray[0] = sortByPositionJob_1.Schedule(); SortByPositionJob sortByPositionJob_2 = new SortByPositionJob { sortArray = nativeArray_2, }; jobHandleArray[1] = sortByPositionJob_2.Schedule(); JobHandle.CompleteAll(jobHandleArray); int visibleEntityTotal = nativeArray_1.Length + nativeArray_2.Length; // Grab sliced arrays and merge them all into one NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntityTotal, Allocator.TempJob); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntityTotal, Allocator.TempJob); FillArraysParallelJob fillArraysParallelJob_1 = new FillArraysParallelJob { nativeArray = nativeArray_1, matrixArray = matrixArray, uvArray = uvArray, startingIndex = 0, }; jobHandleArray[0] = fillArraysParallelJob_1.Schedule(nativeArray_1.Length, 10); FillArraysParallelJob fillArraysParallelJob_2 = new FillArraysParallelJob { nativeArray = nativeArray_2, matrixArray = matrixArray, uvArray = uvArray, startingIndex = nativeArray_1.Length, }; jobHandleArray[1] = fillArraysParallelJob_2.Schedule(nativeArray_2.Length, 10); JobHandle.CompleteAll(jobHandleArray); jobHandleArray.Dispose(); nativeArray_1.Dispose(); nativeArray_2.Dispose(); // Draw MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); Vector4[] uv = new Vector4[1]; Mesh quadMesh = GameController.Instance.Mesh; Material material = GameController.Instance.Material; int shaderPropertyId = Shader.PropertyToID("_MainTex_UV"); int sliceCount = 1023; Matrix4x4[] matrixInstancedArray = new Matrix4x4[sliceCount]; Vector4[] uvInstancedArray = new Vector4[sliceCount]; for (int i = 0; i < visibleEntityTotal; i += sliceCount) { int sliceSize = math.min(visibleEntityTotal - i, sliceCount); 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(); }