IEnumerator UpdateFluid() { while (fluidQueue.Count != 0) { (int index, float density) = fluidQueue.Dequeue(); if (TileUtil.BoundaryCheck(index, mapSize)) { waterDensities[index] = density; } } nativeIndices.Clear(); nativeTiles.CopyFrom(tiles); nativeWaterDensities.CopyFrom(waterDensities); for (int i = 0; i < nativeIsSolid.Length; i++) { nativeIsSolid[i] = tileInformations[i].isSolid; } InitDiffJob initJob = new InitDiffJob { waterDiff = nativeWaterDiff }; initJob.Schedule(nativeWaterDiff.Length, 32).Complete(); InitDirtyJob dirtyJob = new InitDirtyJob { waterChunkDirty = nativeWaterChunkDirty }; dirtyJob.Schedule(nativeWaterChunkDirty.Length, 32).Complete(); yield return(null); CalculateFluidJob fluidJob = new CalculateFluidJob { mapSize = mapSize, chunkSize = chunkSize, numChunks = numChunks, maxFlow = maxFlow, minFlow = minFlow, minDensity = minDensity, maxDensity = maxDensity, maxCompress = maxCompress, flowSpeed = currentFlowSpeed, tiles = nativeTiles, waterDensities = nativeWaterDensities, waterDiff = nativeWaterDiff, isSolid = nativeIsSolid, waterChunkDirty = nativeWaterChunkDirty }; fluidJob.Schedule(tiles.Length, 32).Complete(); yield return(null); ApplyFluidJob applyFluidJob = new ApplyFluidJob { minDensity = minDensity, waterDensities = nativeWaterDensities, waterDiff = nativeWaterDiff }; applyFluidJob.Schedule(waterDensities.Length, 32).Complete(); nativeWaterDensities.CopyTo(waterDensities); yield return(null); FilterRemoveFluidJob filterRemoveFluidJob = new FilterRemoveFluidJob { tiles = nativeTiles, isSolid = nativeIsSolid, minDensity = minDensity, waterDensities = nativeWaterDensities }; filterRemoveFluidJob.ScheduleAppend(nativeIndices, tiles.Length, 32).Complete(); yield return(null); foreach (int fluidIndex in nativeIndices) { waterDensities[fluidIndex] = 0.0f; SetTile(TileUtil.To2DIndex(fluidIndex, mapSize), tileInformations[0].id); } nativeIndices.Clear(); FilterCreateFluidJob filterCreateFluidJob = new FilterCreateFluidJob { tiles = nativeTiles, isSolid = nativeIsSolid, minDensity = minDensity, waterDensities = nativeWaterDensities }; filterCreateFluidJob.ScheduleAppend(nativeIndices, tiles.Length, 32).Complete(); yield return(null); foreach (int fluidIndex in nativeIndices) { SetTile(TileUtil.To2DIndex(fluidIndex, mapSize), waterID); } for (int i = 0; i < nativeWaterChunkDirty.Length; i++) { if (!nativeWaterChunkDirty[i]) { continue; } if (chunks.TryGetValue(TileUtil.To2DIndex(i, numChunks), out TileChunk chunk)) { chunk.SetMeshDirty(); } } fluidUpdator = null; }
public void Execute(int tileIndex) { int2 tilePosition = TileUtil.To2DIndex(tileIndex, mapSize); if (tiles[tileIndex] != waterID) { if (isSolid[tiles[tileIndex]]) { waterDensities[tileIndex] = 0.0f; } return; } if (waterDensities[tileIndex] < minDensity) { waterDensities[tileIndex] = 0; return; } float remainingDensity = waterDensities[tileIndex]; if (remainingDensity <= 0) { return; } waterChunkDirty[TileUtil.To1DIndex(TileUtil.WorldTileToChunk(tilePosition, chunkSize), numChunks)] = true; int2 downPosition = tilePosition + TileUtil.Down; int downIndex = TileUtil.To1DIndex(downPosition, mapSize); if (TileUtil.BoundaryCheck(downPosition, mapSize) && !isSolid[tiles[downIndex]]) { float flow = CalculateStableDensity(remainingDensity + waterDensities[downIndex]) - waterDensities[downIndex]; if (flow > minFlow) { flow *= flowSpeed; } flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity)); waterDiff[tileIndex] -= flow; waterDiff[downIndex] += flow; remainingDensity -= flow; } if (remainingDensity < minDensity) { waterDiff[tileIndex] -= remainingDensity; return; } int2 leftPosition = tilePosition + TileUtil.Left; int leftIndex = TileUtil.To1DIndex(leftPosition, mapSize); if (TileUtil.BoundaryCheck(leftIndex, mapSize) && !isSolid[tiles[leftIndex]]) { float flow = (remainingDensity - waterDensities[leftIndex]) / 4.0f; if (flow > minFlow) { flow *= flowSpeed; } flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity)); waterDiff[tileIndex] -= flow; waterDiff[leftIndex] += flow; remainingDensity -= flow; } if (remainingDensity < minDensity) { waterDiff[tileIndex] -= remainingDensity; return; } int2 rightPosition = tilePosition + TileUtil.Right; int rightIndex = TileUtil.To1DIndex(rightPosition, mapSize); if (TileUtil.BoundaryCheck(rightIndex, mapSize) && !isSolid[tiles[rightIndex]]) { float flow = (remainingDensity - waterDensities[rightIndex]) / 3.0f; if (flow > minFlow) { flow *= flowSpeed; } flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity)); waterDiff[tileIndex] -= flow; waterDiff[rightIndex] += flow; remainingDensity -= flow; } if (remainingDensity < minDensity) { waterDiff[tileIndex] -= remainingDensity; return; } int2 upPosition = tilePosition + TileUtil.Up; int upIndex = TileUtil.To1DIndex(upPosition, mapSize); if (TileUtil.BoundaryCheck(upIndex, mapSize) && !isSolid[tiles[upIndex]]) { float flow = remainingDensity - CalculateStableDensity(remainingDensity + waterDensities[upIndex]); if (flow > minFlow) { flow *= flowSpeed; } flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity)); waterDiff[tileIndex] -= flow; waterDiff[upIndex] += flow; remainingDensity -= flow; } if (remainingDensity < minDensity) { waterDiff[tileIndex] -= remainingDensity; } }