public NodeWalkable GetNextWalkableNodeInDirection(NodeWalkable currentNode, Vector3Int direction, Vector3Int currentUpVector) { Debug.AssertFormat(direction.magnitude == 1, this, "Direction is invalid: {0}", direction); NodeWalkable nextWalkableNode = default; if (m_GridModel != null && currentNode != null) { nextWalkableNode = m_GridModel.TryGetWalkableNode(currentNode.Coordinates + direction); if (nextWalkableNode == null && currentNode.UpVectors.Length > 1) { for (int i = 0; i < currentNode.UpVectors.Length; ++i) { Vector3Int targetUpVector = currentNode.UpVectors[i]; if (currentUpVector != targetUpVector) { Quaternion rotation = Quaternion.FromToRotation(currentUpVector, targetUpVector); Vector3Int rotatedDirection = Vector3IntUtil.Rotate(direction, rotation); nextWalkableNode = m_GridModel.TryGetWalkableNode(currentNode.Coordinates + rotatedDirection); if (nextWalkableNode != null) { break; } } } } } Debug.Assert(nextWalkableNode != null, "Failed to get next walkable node.", this); return(nextWalkableNode); }
private Node CreateGridNode(Vector3Int nodeCoordinates, int gridSize, Transform gridRoot, float nodeSpacing = 1f) { Node node = default; Vector3Int walkableBoundsMin = Vector3Int.zero; Vector3Int walkableBoundsMax = new Vector3Int(gridSize - 1, gridSize - 1, gridSize - 1); Vector3Int surfaceBoundsMin = walkableBoundsMin + Vector3Int.one; Vector3Int surfaceBoundsMax = walkableBoundsMax - Vector3Int.one; if (CheckIfCoordinatesAreOnCubeBoundsSurface(nodeCoordinates, walkableBoundsMin, walkableBoundsMax) == true) { Vector3Int[] upVectors = CalculateNodeUpVectors(nodeCoordinates, walkableBoundsMin, walkableBoundsMax); GameObject nodeView = CreateNodeView(m_WalkableNodePrefab, gridRoot, nodeCoordinates, gridSize, nodeSpacing); node = new NodeWalkable(nodeCoordinates, upVectors, nodeView); } else if (CheckIfCoordinatesAreOnCubeBoundsSurface(nodeCoordinates, surfaceBoundsMin, surfaceBoundsMax) == true) { Vector3Int[] upVectors = CalculateNodeUpVectors(nodeCoordinates, surfaceBoundsMin, surfaceBoundsMax); GameObject nodeView = CreateNodeView(m_SurfaceNodePrefab, gridRoot, nodeCoordinates, gridSize, nodeSpacing); node = new NodeSurface(nodeCoordinates, upVectors, nodeView); } else { node = new NodeEmpty(nodeCoordinates); } return(node); }
public NodeWalkable GetRandomWalkableNode() { int randomIndex = Random.Range(0, m_UnobstructedWalkableGridNodes.Count); NodeWalkable randomWalkableNode = m_UnobstructedWalkableGridNodes[randomIndex]; return(randomWalkableNode); }
private static void AddObstacles(Node[] gridNodes, NodeWalkable playerStartNode, float density, ObstaclePattern pattern, int minPlayerStartClearance) { for (int i = 0; i < gridNodes.Length; ++i) { NodeWalkable walkableNode = gridNodes[i] as NodeWalkable; if (walkableNode != null && walkableNode != playerStartNode) { // Don't add obstacles on edges of the cube. if (walkableNode.UpVectors != null && walkableNode.UpVectors.Length == 1) { if (Random.value <= density) { float nodeDistanceToPlayer = Vector3Int.Distance(playerStartNode.Coordinates, walkableNode.Coordinates); if (nodeDistanceToPlayer > minPlayerStartClearance) { if (CheckIfNodeMatchesObstaclePattern(walkableNode, pattern) == true) { walkableNode.SetAsObstacle(); } } } } } } }
public WorldGridModel(Node[] gridNodes, int gridSize, NodeWalkable playerStartNode) { m_GridNodes = gridNodes; GridSize = gridSize; PlayerStartNode = playerStartNode; CreateGridNodeSubSets(); }
public void UpdatePlayerTarget(IReadOnlyCollection <NodeWalkable> excludedNodes) { if (AreReferencesAssigned == true) { NodeWalkable newPlayerTargetNode = GetNewPlayerTargetNode(excludedNodes); m_GridView.SetNewTargetNode(newPlayerTargetNode, PlayerTargetNode); PlayerTargetNode = newPlayerTargetNode; } }
private static NodeWalkable GetPlayerStartNode(Node[] gridNodes, int gridSize) { Vector3Int playerStartNodeCoordinates = new Vector3Int(gridSize / 2, gridSize / 2, 0); int playerStartNodeIndex = WorldGridUtil.ConvertNodeCoordinatesToIndex(playerStartNodeCoordinates, gridSize); NodeWalkable playerStartNode = gridNodes[playerStartNodeIndex] as NodeWalkable; Debug.Assert(playerStartNode != null, "Invalid player start node!"); return(playerStartNode); }
public NodeWalkable TryGetWalkableNode(Vector3Int nodeCoordinates) { NodeWalkable walkableNode = null; Node node = TryGetNodeAtCoordinates(nodeCoordinates); if (node != null) { walkableNode = node as NodeWalkable; } return(walkableNode); }
private void CreateGridNodeSubSets() { m_UnobstructedWalkableGridNodes = new List <NodeWalkable>(); for (int i = 0; i < m_GridNodes.Length; ++i) { NodeWalkable walkableNode = m_GridNodes[i] as NodeWalkable; if (walkableNode != null && walkableNode.IsObstacle == false) { m_UnobstructedWalkableGridNodes.Add(walkableNode); } } }
private NodeWalkable GetNewPlayerTargetNode(IReadOnlyCollection <NodeWalkable> excludedNodes) { NodeWalkable newPlayerTargetNode = default; if (m_GridModel != null && excludedNodes.Count < m_GridModel.UnobsctructedWalkableNodeCount) { do { newPlayerTargetNode = m_GridModel.GetRandomWalkableNode(); }while (CheckIfWalkableNodeIsExcluded(newPlayerTargetNode, excludedNodes) == true); } Debug.Assert(newPlayerTargetNode != null, "Failed to get new player target node.", this); return(newPlayerTargetNode); }
private bool CheckIfWalkableNodeIsExcluded(NodeWalkable walkableNode, IReadOnlyCollection <NodeWalkable> exludedNodes) { bool isExcluded = false; if (walkableNode != null && exludedNodes != null && exludedNodes.Count > 0) { foreach (NodeWalkable excludedNode in exludedNodes) { if (walkableNode == excludedNode) { isExcluded = true; break; } } } return(isExcluded); }
public void SetNewTargetNode(NodeWalkable targetNode, NodeWalkable previousTargetNode) { if (AreReferencesAssigned == true) { if (previousTargetNode != null) { m_TargetParticles.transform.position = previousTargetNode.ViewPosition; m_TargetParticles.Play(); } if (targetNode != null && targetNode.View != null) { targetNode.View.Show(m_TargetColor, m_TargetEmissionIntensity, true); m_TargetLight.enabled = true; m_TargetLight.color = m_TargetColor; m_TargetLight.transform.position = targetNode.ViewPosition; } } }
public override WorldGridModel GenerateWorldGridModel(Transform gridRoot) { int nodeCount = m_GridSize * m_GridSize * m_GridSize; Node[] gridNodes = new Node[nodeCount]; for (int i = 0; i < nodeCount; ++i) { Vector3Int nodeCoordinates = WorldGridUtil.ConvertNodeIndexToCoordinates(i, m_GridSize); gridNodes[i] = CreateGridNode(nodeCoordinates, m_GridSize, gridRoot); } NodeWalkable playerStartNode = GetPlayerStartNode(gridNodes, m_GridSize); if (m_ObstacleDensity > 0) { AddObstacles(gridNodes, playerStartNode, m_ObstacleDensity, m_ObstaclePattern, m_MinimumPlayerStartClearance); } WorldGridModel gridModel = new WorldGridModel(gridNodes, m_GridSize, playerStartNode); return(gridModel); }
private static bool CheckIfNodeMatchesObstaclePattern(NodeWalkable walkableNode, ObstaclePattern pattern) { bool nodeMatchesObstaclePattern = false; if (walkableNode != null) { Vector3Int nodeCoordinates = walkableNode.Coordinates; Vector3Int nodeUpVector = walkableNode.UpVectors[0]; int remainder = pattern == ObstaclePattern.Even ? 0 : 1; // Add obstacles in a pattern so that the player can always pass through and the player target is always reachable. // Pattern: // #-# // --- // #-# nodeMatchesObstaclePattern = true; nodeMatchesObstaclePattern &= nodeCoordinates.y % 2 == remainder || Mathf.Abs(nodeUpVector.y) > 0; nodeMatchesObstaclePattern &= nodeCoordinates.x % 2 == remainder || Mathf.Abs(nodeUpVector.x) > 0; nodeMatchesObstaclePattern &= nodeCoordinates.z % 2 == remainder || Mathf.Abs(nodeUpVector.z) > 0; } return(nodeMatchesObstaclePattern); }