private Vector3 getPortalPos(int y) { WorldGrid.Cell cell; WorldGrid.Cell cellPlus; do { cell = WorldData.worldGrid.getRandomCell(false, y); if (y + 1 < WorldData.worldGrid.yOffsets.Length) { cellPlus = WorldData.worldGrid.getCell(cell.x, y + 1, cell.z); } else { cellPlus = new WorldGrid.Cell(); cellPlus.blocked = true; } } while (takenCells.Contains(cell)); int layermask = (1 << 19); Ray ray = new Ray(cell.pos + Vector3.up * 5, Vector3.down); RaycastHit hit; Physics.Raycast(ray, out hit, 10, layermask); return(hit.point); }
protected WorldGrid.Cell findTargetCell(Vector3 prefDir) { WorldGrid.Cell target = null; Vector3 testDir; float degInc = 180 / 8; float start = 5; while (target == null && start < 200) { target = probeDir(prefDir, start); if (target != null) { break; } for (float deg = degInc; deg < 180; deg += degInc) { testDir = Quaternion.AngleAxis(deg, Vector3.up) * prefDir; target = probeDir(testDir, start); if (target != null) { break; } testDir = Quaternion.AngleAxis(-deg, Vector3.up) * prefDir; target = probeDir(testDir, start); if (target != null) { break; } } start += 10; } return(target); //This shouldn't happen }
//Determines if there are any colliders inside a cell bool obstacleInCell(WorldGrid.Cell cell) { float modifier = 1.0f; Vector3 halfExtents = new Vector3(WorldData.cellSize / 2, WorldData.cellSize / 2, WorldData.cellSize / 2) * modifier; int layer = (1 << 19); return(Physics.CheckBox(cell.pos, halfExtents, Quaternion.identity, layer)); }
//This is basically a*, if it cant find a path from startPos to any target node, then all the nodes in // the closed list are blocked nodes. void fillAreaIfBlocked(int level, WorldGrid.Cell startCell, WorldGrid.Cell[] targets) { WorldGrid grid = WorldData.worldGrid; Dictionary <Vector3, WorldGrid.Cell> closed = null; foreach (var target in targets) { SortedList <float, WorldGrid.Cell> open = new SortedList <float, WorldGrid.Cell>(new WorldGrid.DuplicateKeyComparer <float>()); //For quickly finding best node to visit closed = new Dictionary <Vector3, WorldGrid.Cell>(); //For quickly looking up closed nodes var goal = target; var current = startCell; grid.resetAStarData(); current.g = 0; open.Add(current.f, current); //Push the start node while (open.Count > 0) { do //Outdated cells might still be in the list { current = open.Values[0]; open.RemoveAt(0); } while (closed.ContainsKey(current.pos) && open.Count > 0); if (current.pos == goal.pos) //Victor { return; // The node is connected to the target, just return } if (open.Count == 0 && closed.ContainsKey(current.pos)) { break; } //Close current tile closed.Add(current.pos, current); for (int i = 0; i < current.plusNeighbours.Count; i++) { var cell = current.plusNeighbours[i]; if (!closed.ContainsKey(cell.pos) && !cell.blocked) { float g = current.g + 1; if (g < cell.g) //New and better G value? { cell.h = Mathf.Abs(goal.x - cell.x) + Mathf.Abs(goal.y - cell.y); cell.g = g; open.Add(cell.f, cell); } } } } } // If the search made it this far, that means the node is blocked in for (int i = 0; i < closed.Count; i++) { closed.ElementAt(i).Value.blocked = true; } }
private void RpcRespawnNPC(GameObject npc) { int y = (Random.Range(0.0f, 1.0f) < 0.3f) ? Random.Range(1, WorldData.yOffsets.Length) : 1; WorldGrid.Cell cell = WorldData.worldGrid.getRandomCell(false, y); //Angle is used to generate a direction float angle = Random.Range(0, Mathf.PI * 2); Vector3 dir = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)); //Spawn npc npc.GetComponent <NPC>().spawn(cell.pos, dir); }
private void CmdSpawnNPC(GameObject npc, int syncFrame) { int y = (Random.Range(0.0f, 1.0f) < 0.3f) ? Random.Range(1, WorldData.yOffsets.Length) : 1; var npcInstance = Instantiate(npc); WorldGrid.Cell cell = WorldData.worldGrid.getRandomCell(false, y); //Angle is used to generate a direction float angle = Random.Range(0, Mathf.PI * 2); Vector3 dir = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)); //Spawn npc npcInstance.GetComponent <NPC>().spawn(cell.pos, dir, syncFrame); NetworkServer.Spawn(npcInstance); }
protected void AStar(WorldGrid.Cell startCell, WorldGrid.Cell goal) { if (goal == null || startCell == null) { return; } Dictionary <Vector3, WorldGrid.Cell> closed = new Dictionary <Vector3, WorldGrid.Cell>(); //For quickly looking up closed nodes SortedList <float, WorldGrid.Cell> open = new SortedList <float, WorldGrid.Cell>(new WorldGrid.DuplicateKeyComparer <float>()); //For quickly finding best node to visit this._path.Clear(); //Clear any old paths this._goal = goal.pos; var current = startCell; this._worldGrid.resetAStarData(); current.g = 0; open.Add(current.f, current); //Push the start node while (open.Count > 0) { do //Outdated cells might still be in the list { current = open.Values[0]; open.RemoveAt(0); } while (closed.ContainsKey(current.pos) && open.Count > 0); if (current.pos == goal.pos) //Victor { WorldGrid.Cell tmp = goal; while (tmp.parent != null) { this._path.Push(tmp); tmp = tmp.parent; } this._path.Push(tmp); return; } if (open.Count == 0 && closed.ContainsKey(current.pos)) { break; } //Close current tile closed.Add(current.pos, current); foreach (var cell in current.neighbours) { if (!closed.ContainsKey(cell.pos) && !cell.blocked) { float g = current.g + Vector3.Distance(cell.pos, current.pos); if (g < cell.g) //New and better G value? { cell.h = Vector3.Distance(cell.pos, goal.pos); cell.g = g; cell.parent = current; open.Add(cell.f, cell); } } } } }
//Finds obstacles in every cell of WorldGrid, and marks them as blocked //Areas that are closed off by blocked cells will also be blocked private IEnumerator findObstacles(System.Action <float> progress) { WorldGrid grid = WorldData.worldGrid; int Iter = 0; int totalIter = grid.yOffsets.Length * grid.cellCount * grid.cellCount * 2; int yieldRate = grid.cellCount; for (int y = 0; y < grid.yOffsets.Length; y++) { for (int z = 0; z < grid.cellCount; z++) { for (int x = 0; x < grid.cellCount; x++) { var cell = grid.getCell(x, y, z); if (!cell.blocked) { cell.blocked = obstacleInCell(cell); } Iter++; if (Iter % yieldRate == 0) { progress((float)Iter / (float)totalIter); yield return(0); } } } } bool lastCellBlocked = false; for (int y = 0; y < grid.yOffsets.Length; y++) { WorldGrid.Cell[] targets = new WorldGrid.Cell[this._islandData.connectPoints[y].childCount]; for (int i = 0; i < targets.Length; i++) { targets[i] = grid.getCell(this._islandData.connectPoints[y].GetChild(i).position); } if (y == 1) { blockWaterInLand(y); } for (int z = 0; z < grid.cellCount; z++) { for (int x = 0; x < grid.cellCount; x++) { var cell = grid.getCell(x, y, z); if (!cell.blocked && lastCellBlocked) { this.fillAreaIfBlocked(y, cell, targets); } lastCellBlocked = cell.blocked; Iter++; if (Iter % yieldRate == 0) { progress((float)Iter / (float)totalIter); yield return(0); } } } } progress(1); }