public void UpdateEmissionRate(ref FireCell cell) { var emission = particles.emission; emission.rate = new ParticleSystem.MinMaxCurve(emissionRateFromFuel.GetValue(cell.fuelRemaining)); // particles.emission = emission; }
public List <FireCell> GetCellNeighbours(FireCell cell) { List <FireCell> neighbours = new List <FireCell>(); for (int i = -1; i <= 1; i += 2) { Vector3 neighbourPositionX = cell.position + new Vector3(i * _grid.radius * 2, 0, 0); Vector3 neighbourPositionY = cell.position + new Vector3(0, i * _grid.radius * 2, 0); Vector3 neighbourPositionZ = cell.position + new Vector3(0, 0, i * _grid.radius * 2); foreach (var c in _grid.gridCells) { if (c.Key == neighbourPositionX && !_burningCells.Contains(c.Value)) { neighbours.Add(c.Value); } else if (c.Key == neighbourPositionY && !_burningCells.Contains(c.Value)) { neighbours.Add(c.Value); } else if (c.Key == neighbourPositionZ && !_burningCells.Contains(c.Value)) { neighbours.Add(c.Value); } } } return(neighbours); }
public void Burning() { if (active) { // Get all surrounding objects Collider[] closeObjects = Physics.OverlapSphere( transform.position * Random.Range(0.6f, 1.3f), parent.radius * Random.Range(0.2f, 1.0f)); foreach (Collider obj in closeObjects) { // Check if it collides with itself if (obj.collider != transform.collider && obj.collider != parent.collider) { Flammable flammable = obj.GetComponent <Flammable>(); FireCell cell = obj.GetComponent <FireCell>(); // Is it a FireCell? if (cell != null) { cell.FireDamage(); } // Is it a Flammable? else if (flammable != null) { flammable.RespondToFire(); } } } } }
void UpdateSpreading() { if (!gameObject || !gameObject.transform || !gameObject.transform.parent) { return; } GameObject Parent = gameObject.transform.parent.gameObject; float nearestCellDist = float.MaxValue; FireCell nearestCell = null; for (int i = 0; i < Parent.transform.childCount; ++i) { FireCell cell = Parent.transform.GetChild(i).gameObject.GetComponent <FireCell>(); if (cell != this && cell) { float magnitude = (cell.transform.position - transform.position).magnitude; if (magnitude < nearestCellDist) { nearestCellDist = magnitude; nearestCell = cell; } } } if (nearestCell && nearestCell.IsBurning) { BurningCounter += Time.deltaTime; } }
public void IgniteCell(ref FireCell newCell) { newCell.InitializeFuelInfo(cellExtents, fuelFromCellDensity); newCell.burnStartTime = Time.time; newCell.groundParticles.StartFire(); newCell.activated = true; activeCells.Add(newCell); }
public void StartFire(Vector3 heatSourcePosition) { if (_state == FireState.Normal) { _hasStartedFire = true; _flames = new Dictionary <Vector3, GameObject>(); FindAllCells(); FireCell nearestCell = FindNearestCell(heatSourcePosition); _burningCells.Add(nearestCell); } }
public void InitializeFireGrid() { activeCells = new List<FireCell> (); depletedCells = new List<FireCell> (); mapSize = ForestController.Instance.mapSize; mapSize.y = ForestController.Instance.maxTerrainHeight; cellsX = Mathf.FloorToInt(mapSize.x / gridSize); cellsY = Mathf.FloorToInt(mapSize.z / gridSize); cells = new FireCell[cellsX,cellsY]; if (particlesContainer) { Destroy(particlesContainer.gameObject); } particlesContainer = new GameObject ("Fire Particles Container").transform; particlesContainer.parent = transform; burntTextureSettings.InitializeTexture(cellsX, cellsY); cellExtents = new Vector3 (gridSize / 2f, mapSize.y / 2f, gridSize / 2f); RaycastHit hit; for (int x = 0; x < cellsX; x++) { for (int y = 0; y < cellsY; y++) { Vector2Int gridPosition = new Vector2Int (x, y); Vector3 centerPoint = new Vector3 (((float)x / (float)cellsX - .5f) * mapSize.x, mapSize.y + .5f, ((float)y / (float)cellsY - .5f) * mapSize.z); Vector3 normal = Vector3.up; if (Physics.Raycast(centerPoint, Vector3.down, out hit, mapSize.y + 20f, ForestController.Instance.terrainLayerMask)) { centerPoint = hit.point; normal = hit.normal; } cells[x, y] = new FireCell (gridPosition, centerPoint, normal); cells[x, y].InitializeFuelInfo(cellExtents, fuelFromCellDensity); GameObject newGroundParticles = GameObject.Instantiate(groundFireParticles, centerPoint, Quaternion.LookRotation(normal)) as GameObject; newGroundParticles.name = groundFireParticles.name + " [" + x.ToString() + "," + y.ToString() + "]"; newGroundParticles.transform.parent = particlesContainer; cells[x, y].groundParticles = newGroundParticles.GetComponent<FireParticleEffect>(); cells[x, y].groundParticles.cell = cells[x, y]; } } }
public void InitializeFireGrid() { activeCells = new List <FireCell> (); depletedCells = new List <FireCell> (); mapSize = ForestController.Instance.mapSize; mapSize.y = ForestController.Instance.maxTerrainHeight; cellsX = Mathf.FloorToInt(mapSize.x / gridSize); cellsY = Mathf.FloorToInt(mapSize.z / gridSize); cells = new FireCell[cellsX, cellsY]; if (particlesContainer) { Destroy(particlesContainer.gameObject); } particlesContainer = new GameObject("Fire Particles Container").transform; particlesContainer.parent = transform; burntTextureSettings.InitializeTexture(cellsX, cellsY); cellExtents = new Vector3(gridSize / 2f, mapSize.y / 2f, gridSize / 2f); RaycastHit hit; for (int x = 0; x < cellsX; x++) { for (int y = 0; y < cellsY; y++) { Vector2Int gridPosition = new Vector2Int(x, y); Vector3 centerPoint = new Vector3(((float)x / (float)cellsX - .5f) * mapSize.x, mapSize.y + .5f, ((float)y / (float)cellsY - .5f) * mapSize.z); Vector3 normal = Vector3.up; if (Physics.Raycast(centerPoint, Vector3.down, out hit, mapSize.y + 20f, ForestController.Instance.terrainLayerMask)) { centerPoint = hit.point; normal = hit.normal; } cells[x, y] = new FireCell(gridPosition, centerPoint, normal); cells[x, y].InitializeFuelInfo(cellExtents, fuelFromCellDensity); GameObject newGroundParticles = GameObject.Instantiate(groundFireParticles, centerPoint, Quaternion.LookRotation(normal)) as GameObject; newGroundParticles.name = groundFireParticles.name + " [" + x.ToString() + "," + y.ToString() + "]"; newGroundParticles.transform.parent = particlesContainer; cells[x, y].groundParticles = newGroundParticles.GetComponent <FireParticleEffect>(); cells[x, y].groundParticles.cell = cells[x, y]; } } }
public void AddCellToGrid(Vector3 position) { FireCell cell = new FireCell(); if (cell != null) { cell.radius = _grid.radius; cell.position = position; cell.settings = fireSettings; if (!_grid.gridCells.ContainsKey(position)) { _grid.gridCells.Add(position, cell); } } }
public FireGrid(float x, float y, Vector3 position) { this.x = (int)x / cellSize; this.y = (int)y / cellSize; grid = new FireCell[this.x, this.y]; //TODO Use jagged array? http://stackoverflow.com/questions/7154592/initializing-two-dimensional-array-of-objects for (int i = 0; i < this.y; i++) { for (int j = 0; j < this.x; j++) { grid[i, j] = new FireCell(); } } }
void Start() { InvokeRepeating("UpdateSpread", 0f, 1.0f); // Control if the object should ignite if (ignite) { GenerateGrid(); // Start a fire at a random position while (true) { FireCell cell = fireGrid[Random.Range(0, fireGrid.Count - 1)]; if (cell.active) { cell.StartFire(); break; } } } }
void AttemptSpread(FireCell initialCell) { for (int i = 0; i < initialCell.adjacentCells.Count; i++) { FireCell adjacentCell = GetCellFromV2Int(initialCell.adjacentCells[i]); if (adjacentCell.activated) { initialCell.adjacentCells.RemoveAt(i); i--; continue; } float spreadAttemptValue = Random.value * Vector3.Dot(initialCell.normal, adjacentCell.normal); if (spreadAttemptValue >= burnSpreadChance.GetValue(adjacentCell.fuelRemaining)) { IgniteCell(ref adjacentCell); initialCell.adjacentCells.RemoveAt(i); i--; continue; } } }
void CheckWaterCollision() { Vector3 Pos = WaterCollisionCheckList[0]; WaterCollisionCheckList.RemoveAt(0); Debug.DrawLine(Pos - Vector3.up * WaterDropRadius, Pos + Vector3.up * WaterDropRadius, Color.red); Debug.DrawLine(Pos - Vector3.left * WaterDropRadius, Pos + Vector3.left * WaterDropRadius, Color.red); Collider2D[] HitObjects = Physics2D.OverlapCircleAll(Pos, WaterDropRadius); foreach (Collider2D coll in HitObjects) { if (coll.CompareTag("forest")) { FireCell cell = coll.gameObject.GetComponent <FireCell>(); if (cell) { cell.CurrentHealth -= WaterDamage; } } else if (coll.CompareTag("enemy")) { HealthBar demon = coll.GetComponent <HealthBar>(); DemonBehavior demon_behavior = coll.GetComponent <DemonBehavior>(); if (GameObject.Find("Player").GetComponent <ScoreComponent>().bDamageBoost) { demon.Health -= WaterDamage * 2; } else { demon.Health -= WaterDamage; } demon_behavior.Hit(); } } }
public void AddAdjacentCells(FireCell initialCell) { int thisX = initialCell.gridPosition.x; int thisY = initialCell.gridPosition.y; for (int x = thisX - 1; x <= thisX + 1; x++) { if (x >= 0 && x < cellsX) { initialCell.adjacentCells.Add(new Vector2Int(x, thisY)); } x++; } for (int y = thisY - 1; y <= thisY + 1; y++) { if (y >= 0 && y < cellsY) { initialCell.adjacentCells.Add(new Vector2Int(thisX, y)); } y++; } }
private FireCell FindNearestCell(Vector3 heatSourcePosition) { FireCell nearestCell = null; float nearestDistance = 0; foreach (var cell in _grid.gridCells) { if (nearestCell == null) { nearestCell = cell.Value; nearestDistance = Vector3.Distance(cell.Key, heatSourcePosition); } else { if (Vector3.Distance(cell.Key, heatSourcePosition) < nearestDistance) { nearestCell = cell.Value; nearestDistance = Vector3.Distance(cell.Key, heatSourcePosition); } } } return(nearestCell); }
public void Water() { if (active) { WaterDamage(); // Get all surrounding objects Collider[] closeObjects = Physics.OverlapSphere(transform.position, parent.radius); foreach (Collider obj in closeObjects) { // Check if it collides with itself if (obj.collider != transform.collider && obj.collider != parent.collider) { FireCell cell = obj.GetComponent <FireCell>(); if (cell != null) { cell.WaterDamage(); } } } } }
private void GenerateGrid() { Bounds bounds = transform.collider.bounds; Vector3 min = bounds.min; Vector3 max = bounds.max; for (float x = min.x; x <= max.x; x = x + cellSize) { for (float y = min.y; y <= max.y; y = y + cellSize) { for (float z = min.z; z <= max.z; z = z + cellSize) { Vector3 pos = new Vector3(x, y, z); if (positionInsideThis(pos)) { FireCell cell = (FireCell)Instantiate(fireCell, pos, transform.rotation); cell.Instantiate(this); fireGrid.Add(cell); } } } } }
// Update is called once per frame void Update() { timeLeft -= Time.deltaTime; //Debug.Log(timeLeft); if (Pathfinding.Target.Equals(string.Empty) && timeLeft < 0) { if (Pathfinding.Target != null) { if (room == null || !Pathfinding.CurrentRoom.Equals(room.name)) { room = GameObject.Find(Pathfinding.CurrentRoom); roomInfo = room.GetComponent <RoomInformation>(); roomFlammable = room.GetComponent <Flammable>(); } if (roomInfo.FireCount > 0) { if (currentTarget == null || !currentTarget.IsBurning) { FireCell[] fires = roomFlammable.GetComponentsInChildren <FireCell>(); if (currentTarget == null) { for (int i = 0; i < fires.Length; i++) { if (fires[i].IsBurning) { currentTarget = fires[i]; break; } } } else { Collider[] colliders = Physics.OverlapSphere(currentTarget.transform.position, roomFlammable.cellSize); Debug.Log(colliders.Length); for (int i = 0; i < colliders.Length; i++) { FireCell cell = colliders[i].GetComponent <FireCell>(); if (cell != null && cell.IsBurning) { currentTarget = cell; break; } } if (!currentTarget.IsBurning) { currentTarget = null; } } } if (currentTarget != null) { transform.LookAt(currentTarget.transform); //Water.ShootFluidParticle(this.transform); Water.ShootFluidParticle(this.transform); } } } timeLeft = timeBetweenShots; } }
public void AddAdjacentCells (FireCell initialCell) { int thisX = initialCell.gridPosition.x; int thisY = initialCell.gridPosition.y; for (int x = thisX - 1; x <= thisX + 1; x++) { if (x >= 0 && x < cellsX) { initialCell.adjacentCells.Add(new Vector2Int(x, thisY)); } x++; } for (int y = thisY - 1; y <= thisY + 1; y++) { if (y >= 0 && y < cellsY) { initialCell.adjacentCells.Add(new Vector2Int(thisX, y)); } y++; } }
public void IgniteCell (ref FireCell newCell) { newCell.InitializeFuelInfo(cellExtents, fuelFromCellDensity); newCell.burnStartTime = Time.time; newCell.groundParticles.StartFire(); newCell.activated = true; activeCells.Add(newCell); }
public void UpdateEmissionRate (ref FireCell cell) { var emission = particles.emission; emission.rate = new ParticleSystem.MinMaxCurve(emissionRateFromFuel.GetValue(cell.fuelRemaining)); // particles.emission = emission; }
void FixedUpdate() { // Remove all particles that have fallen too low, have expired or hit fire if (RemoveExpiredParticles) { Particles.RemoveAll(p => p.ToBeRemoved || (p.Position.y < -1) || p.Expiry <= 0); } else { Particles.RemoveAll(p => p.ToBeRemoved || (p.Position.y < -1)); } // Add new particles Particles.AddRange(newParticles); newParticles.Clear(); int newParticleCount = Particles.Count; if (newParticleCount != particleCount) { particleCount = newParticleCount; Debug.Log(particleCount + " fluid particles."); } // Predict the positions of the particles // Lines 1-4 from the algorithm in the paper foreach (FluidParticle p in Particles) { // Apply gravity p.Velocity -= Gravity; Vector3 newPosition = p.Position + p.Velocity; RaycastHit hit = new RaycastHit(); if (Physics.Linecast(p.Position, newPosition + ParticleDiameter * (newPosition - p.Position).normalized, out hit)) { if (hit.normal.y != 0) { p.Velocity += Gravity; } p.Velocity = Vector3.Reflect(p.Velocity * ParticleElasticity, hit.normal); newPosition = p.Position + p.Velocity; FireCell fireCell = hit.collider.GetComponent <FireCell>(); if (fireCell != null) { fireCell.Water(); p.ToBeRemoved = true; } } p.PredictedPosition = newPosition; } // Find neighbours of each particle // Lines 5-7 from the algorithm in the paper List <FluidParticle>[] neighbours = new List <FluidParticle> [Particles.Count]; for (int i = 0; i < Particles.Count; i++) { FluidParticle p = Particles[i]; p.Index = i; List <FluidParticle> foundNeighbours = new List <FluidParticle>(); foreach (FluidParticle potentialNeighbour in Particles) { if (potentialNeighbour != p && Vector3.Distance(potentialNeighbour.Position, p.Position) < NeighbourDistance) { foundNeighbours.Add(potentialNeighbour); } } neighbours[i] = foundNeighbours; } float[] lambdas = new float[Particles.Count]; Vector3[] deltaPos = new Vector3[Particles.Count]; // Refine the predicted positions by taking incompressibilty into account // Lines 8-19 from the algorithm in the paper for (int iteration = 0; iteration < SolverIterations; iteration++) { // Find lambda for each particle // Lines 9-11 from the algorithm in the paper for (int i = 0; i < Particles.Count; i++) { FluidParticle p = Particles[i]; List <FluidParticle> foundNeighbours = neighbours[i]; float pi = StdSPHDensityEstimator(p, foundNeighbours); float c = pi / RestDensity - 1; float deltaCSum = DerivativeCSum(p, foundNeighbours); lambdas[i] = -c / deltaCSum; } // Find more finely predicted positions // Lines 12-15 from the algorithm in the paper for (int i = 0; i < Particles.Count; i++) { FluidParticle p = Particles[i]; List <FluidParticle> foundNeighbours = neighbours[i]; deltaPos[i] = Vector3.zero; foreach (FluidParticle neigbour in foundNeighbours) { deltaPos[i] += (lambdas[i] + lambdas[neigbour.Index]) * Vector3.Normalize(p.PredictedPosition - neigbour.Position) * SpikyDerivative(p, neigbour); } deltaPos[i] = 1 / RestDensity * deltaPos[i]; Vector3 newPosition = p.PredictedPosition + deltaPos[i]; if (Physics.Linecast(p.PredictedPosition, newPosition + ParticleDiameter * (newPosition - p.Position).normalized)) { deltaPos[i] = Vector3.zero; } } // Use the new positions // Lines 16-18 from the algorithm in the paper for (int i = 0; i < Particles.Count; i++) { FluidParticle p = Particles[i]; p.PredictedPosition += deltaPos[i]; } } // Actually set the new positions and count down the expiry of the particles. foreach (FluidParticle p in Particles) { p.Velocity = p.PredictedPosition - p.Position; p.Position = p.PredictedPosition; p.Expiry--; } }
void AttemptSpread (FireCell initialCell) { for(int i = 0; i < initialCell.adjacentCells.Count; i++) { FireCell adjacentCell = GetCellFromV2Int(initialCell.adjacentCells[i]); if (adjacentCell.activated) { initialCell.adjacentCells.RemoveAt(i); i--; continue; } float spreadAttemptValue = Random.value * Vector3.Dot(initialCell.normal, adjacentCell.normal); if (spreadAttemptValue >= burnSpreadChance.GetValue(adjacentCell.fuelRemaining)) { IgniteCell(ref adjacentCell); initialCell.adjacentCells.RemoveAt(i); i--; continue; } } }