public void Step() { if (filterActive) { PipeObject input = atmosNeighbours[0]; PipeObject outputFiltered = atmosNeighbours[3]; PipeObject outputOther = atmosNeighbours[1]; // Return when there is no gas if (input == null || input.GetTotalMoles() <= 1f || outputFiltered == null || outputOther == null) { return; } AtmosContainer inputContainer = input.GetAtmosContainer(); // Both outputs must not be blocked if (outputFiltered.GetPressure() <= _targetPressure && outputOther.GetPressure() <= _targetPressure) { // Use the pipe with the highest pressure as reference PipeObject nearestOutput = (outputFiltered.GetPressure() > outputOther.GetPressure()) ? outputFiltered : outputOther; // Calculate necessary moles to transfer using PV=nRT float pressureDifference = _targetPressure - nearestOutput.GetPressure(); float transferMoles = pressureDifference * 1000 * nearestOutput.volume / (nearestOutput.GetAtmosContainer().GetTemperature() * Gas.gasConstant); // We can not transfer more moles than the machinery allows transferMoles = Mathf.Min(Gas.maxMoleTransfer, transferMoles); // We can't transfer more moles than there are in the input if (transferMoles > input.GetTotalMoles()) { transferMoles = input.GetTotalMoles(); } // for (int i = 0; i < Gas.numOfGases; i++) foreach (AtmosGasses gas in Enum.GetValues(typeof(AtmosGasses))) { // Divide the moles according to their percentage float molePerGas = (inputContainer.GetGas(gas) / input.GetTotalMoles()) * transferMoles; if (inputContainer.GetGas(gas) > 0f) { input.RemoveGas(gas, molePerGas); // Determine output based on filtering setting if (IsFiltered(gas)) { outputFiltered.AddGas(gas, molePerGas); } else { outputOther.AddGas(gas, molePerGas); } } } } } }
public void Step() { if (atmosNeighbour) { if (atmosNeighbour.GetTotalMoles() > 0.1f) { float[] tileGas = tile.atmos.GetAtmosContainer().GetGasses(); for (int i = 0; i < Gas.numOfGases; i++) { float gasToTransfer = atmosNeighbour.GetAtmosContainer().GetGas(i); tile.atmos.AddGas(i, gasToTransfer); atmosNeighbour.RemoveGas(i, gasToTransfer); } } } }
public void Step() { // If both sides of the pump are connected if (pumpActive && atmosNeighbours[0] && atmosNeighbours[1]) { PipeObject input = atmosNeighbours[0]; PipeObject output = atmosNeighbours[1]; if (input.GetTotalMoles() == 0) { return; } AtmosContainer inputContainer = input.GetAtmosContainer(); // And the output pressure is acceptable if (pumpType == PumpType.Pressure) { if (output.GetPressure() <= TargetPressure - 0.1f) { float totalMoles = input.GetTotalMoles(); // Calculate necessary moles to transfer using PV=nRT float pressureDifference = TargetPressure - output.GetPressure(); float transferMoles = pressureDifference * 1000 * output.volume / (output.GetAtmosContainer().GetTemperature() * Gas.gasConstant); // We can not transfer more moles than the machinery allows transferMoles = Mathf.Min(Gas.maxMoleTransfer, transferMoles); // We can't transfer more moles than there are if (transferMoles > totalMoles) { transferMoles = totalMoles; } for (int i = 0; i < Gas.numOfGases; i++) { // Divide the moles according to their percentage float molePerGas = (inputContainer.GetGas(i) / totalMoles) * transferMoles; if (inputContainer.GetGas(i) > 0f) { input.RemoveGas(i, molePerGas); output.AddGas(i, molePerGas); } } } } // TODO: different pump speeds between volume/pressure pumps else if (pumpType == PumpType.Volume) { // At 200 L/s float inputVolume = input.volume * 1000 / CurrentVolumeSetting; float transferMoles = input.GetPressure() * 1000 * inputVolume / (input.GetAtmosContainer().GetTemperature() * Gas.gasConstant); float totalMoles = input.GetTotalMoles(); // We can not transfer more moles than the machinery allows transferMoles = Mathf.Min(molesPerStep, transferMoles); for (int i = 0; i < Gas.numOfGases; i++) { // We can't transfer more moles than there are if (transferMoles > totalMoles) { transferMoles = totalMoles; } // Divide the moles according to their percentage float molePerGas = (inputContainer.GetGas(i) / totalMoles) * transferMoles; if (inputContainer.GetGas(i) >= molePerGas) { input.RemoveGas(i, molePerGas); output.AddGas(i, molePerGas); } } } } }
public void Step() { if (mixerActive) { ratioOnetoTwo = InputOneAmount / 100f; PipeObject input1 = atmosNeighbours[0]; PipeObject input2 = atmosNeighbours[3]; PipeObject output = atmosNeighbours[1]; if (!input1 || !input2 || !output) { return; } float[] inputGasses1 = input1.GetAtmosContainer().GetGasses(); float[] inputGasses2 = input2.GetAtmosContainer().GetGasses(); float[] outputGasses = output.GetAtmosContainer().GetGasses(); if (input1.GetTotalMoles() <= 1f || input2.GetTotalMoles() <= 1f) { return; } if (output.GetPressure() <= _targetPressure) { float totalMoles = output.GetTotalMoles(); // Calculate necessary moles to transfer using PV=nRT float pressureDifference = _targetPressure - output.GetPressure(); float transferMoles = pressureDifference * 1000 * output.volume / (output.GetAtmosContainer().GetTemperature() * Gas.gasConstant); // We can not transfer more moles than the machinery allows transferMoles = Mathf.Min(Gas.maxMoleTransfer, transferMoles); float transfer_moles1 = ratioOnetoTwo * transferMoles; float transfer_moles2 = (1f - ratioOnetoTwo) * transferMoles; // We can't transfer more moles than there are float inputMoles1 = input1.GetTotalMoles(); float inputMoles2 = input2.GetTotalMoles(); // If one of the inputs didn't contain enough gas, scale the other down if (transfer_moles1 > input1.GetTotalMoles()) { transfer_moles2 = input1.GetTotalMoles() * (1 / ratioOnetoTwo) * (1 - ratioOnetoTwo); transfer_moles1 = input1.GetTotalMoles(); } if (transfer_moles2 > input2.GetTotalMoles()) { transfer_moles1 = input2.GetTotalMoles() * (1 / (1 - ratioOnetoTwo)) * ratioOnetoTwo; transfer_moles2 = input2.GetTotalMoles(); } if (transfer_moles1 > inputMoles1 || transfer_moles2 > inputMoles2) { Debug.LogError("More gas to be transfered than possible"); } for (int i = 0; i < Gas.numOfGases; i++) { // Input 1 and input 2 float molePerGas1 = (inputGasses1[i] / inputMoles1) * transfer_moles1; float molePerGas2 = (inputGasses2[i] / inputMoles2) * transfer_moles2; if (inputGasses1[i] >= molePerGas1 && inputGasses1[i] > 0.1f) { input1.GetAtmosContainer().RemoveGas(i, molePerGas1); output.GetAtmosContainer().AddGas(i, molePerGas1); } if (inputGasses2[i] >= molePerGas2 && inputGasses2[i] > 0.1f) { input2.GetAtmosContainer().RemoveGas(i, molePerGas2); output.GetAtmosContainer().AddGas(i, molePerGas2); } } input1.SetStateActive(); input2.SetStateActive(); output.SetStateActive(); } } }
public void Step() { bool ventActive = false; if (deviceActive) { PipeObject input = connectedPipe; AtmosObject output = GetComponentInParent <TileObject>().atmos; if (input != null || input.GetTotalMoles() > 0) { AtmosContainer inputContainer = input.GetAtmosContainer(); if (mode == OperatingMode.External) { // If the output pressure is acceptable if (output.GetPressure() <= TargetPressure - 1f) { ventActive = true; float totalMoles = input.GetTotalMoles(); // Calculate necessary moles to transfer using PV=nRT float pressureDifference = TargetPressure - output.GetPressure(); float transferMoles = pressureDifference * 1000 * output.GetAtmosContainer().Volume / (output.GetAtmosContainer().GetTemperature() * Gas.gasConstant); // We can not transfer more moles than the machinery allows transferMoles = Mathf.Min(Gas.maxMoleTransfer, transferMoles); // We can't transfer more moles than there are if (transferMoles > totalMoles) { transferMoles = totalMoles; } for (int i = 0; i < Gas.numOfGases; i++) { // Divide the moles according to their percentage float molePerGas = (inputContainer.GetGas(i) / totalMoles) * transferMoles; if (inputContainer.GetGas(i) > 0f) { input.RemoveGas(i, molePerGas); output.AddGas(i, molePerGas); } } } } else if (mode == OperatingMode.Internal) { // If the output pressure is acceptable if (input.GetPressure() >= TargetPressure + 1f) { ventActive = true; float totalMoles = input.GetTotalMoles(); // Calculate necessary moles to transfer using PV=nRT float pressureDifference = input.GetPressure() - TargetPressure; float transferMoles = pressureDifference * 1000 * input.GetAtmosContainer().Volume / (input.GetAtmosContainer().GetTemperature() * Gas.gasConstant); // We can not transfer more moles than the machinery allows transferMoles = Mathf.Min(Gas.maxMoleTransfer, transferMoles); // We can't transfer more moles than there are in the input if (transferMoles > totalMoles) { transferMoles = totalMoles; } for (int i = 0; i < Gas.numOfGases; i++) { // Divide the moles according to their percentage float molePerGas = (inputContainer.GetGas(i) / totalMoles) * transferMoles; if (inputContainer.GetGas(i) > 0f) { input.RemoveGas(i, molePerGas); output.AddGas(i, molePerGas); } } } } } } // Update the animator anim.SetBool("ventActive", ventActive); anim.SetBool("deviceActive", deviceActive); }
public void Step() { int numOfTiles = 0; bool scrubActive = false; switch (range) { case Range.Normal: numOfTiles = 1; break; case Range.Extended: numOfTiles = 5; break; } if (deviceActive) { // We loop 1 or 5 times based on the range setting for (int i = 0; i < numOfTiles; i++) { if (i == 0) { if (input == null) { input = GetComponentInParent <TileObject>().atmos; } } else { input = atmosNeighbours[i - 1]; } PipeObject output = connectedPipe; if (input == null || input.GetTotalMoles() == 0 || output == null || mode == OperatingMode.Off) { return; } AtmosContainer inputContainer = input.GetAtmosContainer(); AtmosContainer outputContainer = output.GetAtmosContainer(); // If the output pressure is acceptable if (output.GetPressure() <= TargetPressure - 1f) { float totalMoles = input.GetTotalMoles(); // Calculate necessary moles to transfer using PV=nRT float pressureDifference = _targetPressure - output.GetPressure(); float transferMoles = pressureDifference * 1000 * output.volume / (output.GetAtmosContainer().GetTemperature() * Gas.gasConstant); // We can not transfer more moles than the machinery allows transferMoles = Mathf.Min(Gas.maxMoleTransfer, transferMoles); // We don't transfer tiny amounts transferMoles = Mathf.Max(transferMoles, Gas.minMoleTransfer); // We can't transfer more moles than there are in the input if (transferMoles > totalMoles) { transferMoles = totalMoles; } for (int j = 0; j < atmosGasses.Length; j++) { if (mode == OperatingMode.Siphoning) { scrubActive = true; // Divide the moles according to their percentage float molePerGas = (inputContainer.GetGas(atmosGasses[j]) / input.GetTotalMoles()) * transferMoles; if (inputContainer.GetGas(atmosGasses[j]) > 0f) { input.RemoveGas(atmosGasses[j], molePerGas); output.AddGas(atmosGasses[j], molePerGas); } } // If scrubbing, remove only filtered gas if (mode == OperatingMode.Scrubbing && IsFiltered(atmosGasses[j])) { if (inputContainer.GetGas(atmosGasses[j]) > 0f) { scrubActive = true; // To avoid leaving a small amount of a certain gas, we apply the min threshold again float molePerGas = Mathf.Min(transferMoles, inputContainer.GetGas(atmosGasses[j])); input.RemoveGas(atmosGasses[j], molePerGas); output.AddGas(atmosGasses[j], molePerGas); } } } } } } // Update the animator anim.SetBool("scrubActive", scrubActive); anim.SetBool("deviceActive", deviceActive); }
public void Step() { // If both sides of the pump are connected if (pumpActive && atmosNeighbours[0] && atmosNeighbours[1]) { PipeObject input = atmosNeighbours[0]; PipeObject output = atmosNeighbours[1]; if (input.GetTotalMoles() == 0) { return; } float[] inputGasses = input.GetAtmosContainer().GetGasses(); float[] outputGasses = output.GetAtmosContainer().GetGasses(); // And the output pressure is acceptable if (pumpType == PumpType.Pressure) { if (output.GetPressure() <= TargetPressure - 0.1f) { float totalMoles = input.GetTotalMoles(); // Calculate necessary moles to transfer using PV=nRT float pressureDifference = TargetPressure - output.GetPressure(); float transferMoles = pressureDifference * 1000 * output.volume / (output.GetAtmosContainer().GetTemperature() * Gas.gasConstant); // Reach our target pressure in N steps transferMoles = transferMoles / stepsToEqualize; // We can't transfer more moles than there are if (transferMoles > totalMoles) { transferMoles = totalMoles; } for (int i = 0; i < Gas.numOfGases; i++) { // Divide the moles according to their percentage float molePerGas = (inputGasses[i] / totalMoles) * transferMoles; if (inputGasses[i] > 0f) { inputGasses[i] -= molePerGas; outputGasses[i] += molePerGas; } } input.SetStateActive(); output.SetStateActive(); } } // TODO: different pump speeds between volume/pressure pumps else if (pumpType == PumpType.Volume) { // At 200 L/s float inputVolume = input.volume * 1000 / CurrentVolumeSetting; float transferMoles = input.GetPressure() * 1000 * inputVolume / (input.GetAtmosContainer().GetTemperature() * Gas.gasConstant); float totalMoles = input.GetTotalMoles(); for (int i = 0; i < Gas.numOfGases; i++) { // We can't transfer more moles than there are if (transferMoles > totalMoles) { transferMoles = totalMoles; } // Divide the moles according to their percentage float molePerGas = (inputGasses[i] / totalMoles) * transferMoles; if (inputGasses[i] >= molePerGas) { inputGasses[i] -= molePerGas; outputGasses[i] += molePerGas; input.SetStateActive(); output.SetStateActive(); } } } } }
// Should be moved to the Atmos editor in the future private void OnDrawGizmos() { float drawSize = 0.8f; #if UNITY_EDITOR if (!EditorApplication.isPlaying) { return; } #endif if (drawDebug) { // For each tile in the tilemap foreach (TileObject tile in tileManager.GetAllTiles()) { // ugly hack to get coordinates string[] coords = tile.name.Split(','); int xTemp = Int32.Parse(coords[0].Replace("[", "")); int yTemp = Int32.Parse(coords[1].Replace("]", "")); var realcoords = tileManager.GetPosition(xTemp, yTemp); float x = realcoords.x; float y = realcoords.z; Vector3 draw = new Vector3(x, 0, y) / 1f; Color state; switch (tile.atmos.GetState()) { case AtmosStates.Active: state = new Color(0, 0, 0, 0); break; case AtmosStates.Semiactive: state = new Color(0, 0, 0, 0.8f); break; case AtmosStates.Inactive: state = new Color(0, 0, 0, 0.8f); break; default: state = new Color(0, 0, 0, 1); break; } float pressure; if (drawTiles) { if (tile.atmos.GetState() == AtmosStates.Blocked) { Gizmos.color = new Color(0.2f, 0.2f, 0.2f, 1f); // Draw black cube where atmos flow is blocked if (drawWall) { Gizmos.DrawCube(new Vector3(x, 0.5f, y), new Vector3(1, 2, 1)); } } else { switch (drawView) { case ViewType.Content: float[] gases = new float[5]; Color[] colors = new Color[] { Color.yellow, Color.white, Color.gray, Color.magenta }; float offset = 0f; for (int k = 0; k < 4; ++k) { float moles = tile.atmos.GetAtmosContainer().GetGasses()[k] / 30f; if (moles != 0f) { Gizmos.color = colors[k] - state; if (drawAll || k == 3) // Only draw plasma { Gizmos.DrawCube(new Vector3(x, moles / 2f + offset, y), new Vector3(1 * drawSize, moles, 1 * drawSize)); offset += moles; } } } break; case ViewType.Pressure: pressure = tile.atmos.GetPressure() / 160f; if (drawAll || tile.atmos.GetState() == AtmosStates.Active) { Gizmos.color = Color.white - state; Gizmos.DrawCube(new Vector3(x, pressure / 2f, y), new Vector3(1 * drawSize, pressure, 1 * drawSize)); } break; case ViewType.Temperature: float temperatue = tile.atmos.GetAtmosContainer().GetTemperature() / 100f; Gizmos.color = Color.red - state; Gizmos.DrawCube(new Vector3(x, temperatue / 2f, y), new Vector3(1 * drawSize, temperatue, 1 * drawSize)); break; case ViewType.Combined: pressure = tile.atmos.GetPressure() / 30f; Gizmos.color = new Color(tile.atmos.GetAtmosContainer().GetTemperature() / 500f, 0, 0, 1) - state; Gizmos.DrawCube(new Vector3(x, pressure / 2f, y), new Vector3(1 * drawSize, pressure, 1 * drawSize)); break; case ViewType.Wind: Gizmos.color = Color.white; Gizmos.DrawLine(new Vector3(x, 0, y), new Vector3(x + Mathf.Clamp(tile.atmos.GetVelocity().x, -1, 1), 0, y + Mathf.Clamp(tile.atmos.GetVelocity().y, -1, 1))); break; } } } // Draw pipe contents if (showPipes) { PipeObject pipe = tile.GetComponentInChildren <PipeObject>(); if (pipe) { switch (pipe.GetState()) { case AtmosStates.Active: state = new Color(0, 0, 0, 0); break; case AtmosStates.Semiactive: state = new Color(0, 0, 0, 0.8f); break; case AtmosStates.Inactive: state = new Color(0, 0, 0, 0.8f); break; default: state = new Color(0, 0, 0, 1); break; } switch (drawView) { case ViewType.Content: float[] gases = new float[5]; Color[] colors = new Color[] { Color.yellow, Color.white, Color.gray, Color.magenta }; float offset = 0f; for (int k = 0; k < 4; ++k) { float moles = pipe.GetAtmosContainer().GetGasses()[k] / 30f; if (moles != 0f) { Gizmos.color = colors[k] - state; if (drawAll || k == 3) // Only draw plasma { Gizmos.DrawCube(new Vector3(x, moles / 2f + offset, y), new Vector3(0.5f * drawSize, moles, 0.5f * drawSize)); offset += moles; } } } break; case ViewType.Pressure: pressure = pipe.GetPressure() / 160f; if (drawAll || pipe.GetState() == AtmosStates.Active) { Gizmos.color = Color.white - state; Gizmos.DrawCube(new Vector3(x, pressure / 2f, y), new Vector3(0.5f * drawSize, pressure, 0.5f * drawSize)); } break; case ViewType.Temperature: float temperatue = pipe.GetAtmosContainer().GetTemperature() / 100f; Gizmos.color = Color.red - state; Gizmos.DrawCube(new Vector3(x, temperatue / 2f, y), new Vector3(0.5f * drawSize, temperatue, 0.5f * drawSize)); break; case ViewType.Combined: pressure = pipe.GetPressure() / 30f; Gizmos.color = new Color(pipe.GetAtmosContainer().GetTemperature() / 500f, 0, 0, 1) - state; Gizmos.DrawCube(new Vector3(x, pressure / 2f, y), new Vector3(0.5f * drawSize, pressure, 0.5f * drawSize)); break; } } } } } }
void Update() { #if UNITY_EDITOR if (!EditorApplication.isPlaying) { return; } #endif if (Time.fixedTime >= lastStep) { activeTiles = Step(); if (showMessages) { Debug.Log("Atmos loop took: " + (Time.fixedTime - lastStep) + " seconds, simulating " + activeTiles + " atmos tiles. Fixed update rate: " + updateRate); } activeTiles = 0; lastStep = Time.fixedTime + updateRate; } // Display atmos tile contents if the editor window is open if (drawDebug) { Vector3 hit = GetMouse(); Vector3 position = new Vector3(hit.x, 0, hit.z); Vector3 snappedPosition = tileManager.GetPositionClosestTo(position); if (snappedPosition != null) { TileObject tile = tileManager.GetTile(snappedPosition); if (tile == null) { return; } if (Time.fixedTime > lastClick + 1) { if (Input.GetMouseButton(0)) { if (drawTiles) { if (isAddingGas) { tile.atmos.AddGas(gasToAdd, 60f); } else { Debug.Log("Tile, Pressure (kPa): " + tile.atmos.GetPressure() + " Temperature (K): " + tile.atmos.GetAtmosContainer().GetTemperature() + " State: " + tile.atmos.GetState().ToString() + "\t" + " Oxygen content: " + tile.atmos.GetAtmosContainer().GetGasses()[0] + " Nitrogen content: " + tile.atmos.GetAtmosContainer().GetGasses()[1] + " Carbon Dioxide content: " + tile.atmos.GetAtmosContainer().GetGasses()[2] + " Plasma content: " + tile.atmos.GetAtmosContainer().GetGasses()[3]); lastClick = Time.fixedTime; } } else if (showPipes) { PipeObject pipe = tile.GetComponentInChildren <PipeObject>(); if (pipe) { if (isAddingGas) { pipe.AddGas(gasToAdd, 30f); } else { Debug.Log("Pipe, Pressure (kPa): " + pipe.GetPressure() + " Temperature (K): " + pipe.GetAtmosContainer().GetTemperature() + " State: " + pipe.GetState().ToString() + "\t" + " Oxygen content: " + pipe.GetAtmosContainer().GetGasses()[0] + " Nitrogen content: " + pipe.GetAtmosContainer().GetGasses()[1] + " Carbon Dioxide content: " + pipe.GetAtmosContainer().GetGasses()[2] + " Plasma content: " + pipe.GetAtmosContainer().GetGasses()[3]); lastClick = Time.fixedTime; } } else { Debug.Log("No pipe found on the clicked tile"); lastClick = Time.fixedTime; } } } else if (Input.GetKeyDown(KeyCode.Escape)) { isAddingGas = false; } } } } }