コード例 #1
0
        public int MoveToBestSpot()
        {
            //print("MoveToBestSpot()");
            if (CurrentActionPoints <= 0)
            {
                return((int)BTNode.EState.Failure);
            }

            Checkpoint  checkpointTarget = GetClosestCheckpoint();
            MBGraphNode checkpointNode   = checkpointTarget == null ? null : checkpointTarget.node;

            if (checkpointNode == null)
            {
                return((int)BTNode.EState.Failure);
            }

            // get the closest reachable node to the checkpoint/goal
            GraphNode <GameObject> optimalGraphNode = reachableNodeIds.Count > 0 ? GameplayManager.Instance.gridGraph.graph[reachableNodeIds[0]] : null;
            float dist = Mathf.Infinity;

            foreach (string nodeId in reachableNodeIds)
            {
                GraphNode <GameObject> graphNode = GameplayManager.Instance.gridGraph.graph[nodeId];
                float tempDist = (graphNode.Data.transform.position - checkpointNode.transform.position).magnitude;
                if (tempDist < dist)
                {
                    optimalGraphNode = graphNode;
                    dist             = tempDist;
                }
            }

            if (optimalGraphNode != null)
            {
                List <GraphNode <GameObject> > path = pathFinding.FindPath(PositionNode.nodeId, optimalGraphNode.Id, MovementHeuristic, checkpoints.Count <= 1);

                if (path.Count > 0)
                {
                    path.RemoveAt(0);
                }
                if (path.Count == 0)
                {
                    return((int)BTNode.EState.Failure);
                }

                Move(path);

                //print("MoveToBestSpot: " + path.Count);
                //foreach (GraphNode<GameObject> gnode in path)
                //{
                //    print(gnode.Data.transform.localPosition);
                //}

                return((int)BTNode.EState.Success);
            }
            else
            {
                return((int)BTNode.EState.Failure); // <- we cannot move anymore
            }
        }
コード例 #2
0
 /// <summary>
 /// Resets the behavior tree properties. This function is called each time before the behavior tree is evaluated. <br />
 /// See <see cref="BehaviorTree.Evaluate"/>
 /// </summary>
 private void ResetBehaviorTreeProperties()
 {
     itemToUseIndex     = -1;
     playerAttackTarget = null;
     playerAttackThreats.Clear();
     reachableNodeIds.Clear();
     moveTargetNode = null;
     nodeToSpillOn  = null;
 }
コード例 #3
0
 private void Awake()
 {
     Collider[] hitColliders = Physics.OverlapSphere(transform.position, 1.5f);
     foreach (var hitCollider in hitColliders)
     {
         if (hitCollider.tag == "Node")
         {
             MBGraphNode positionNode = hitCollider.gameObject.GetComponent <MBGraphNode>();
             powerUpScript.PositionNode = positionNode;
             transform.position         = new Vector3(positionNode.transform.position.x, transform.position.y, positionNode.transform.position.z);
             transform.parent           = positionNode.transform;
         }
     }
 }
コード例 #4
0
        private void ConnectGridNodes(MBGraph target, MBGraphNode nodeA, MBGraphNode nodeB)
        {
            Vector3 direction     = nodeB.transform.position - nodeA.transform.position;
            bool    shouldConnect = true;

            if (target.__detectCollisions)
            {
                List <RaycastHit> hits = FilterRaycastHits(target, Physics.SphereCastAll(nodeA.transform.position, 0.25f, direction, direction.magnitude));
                shouldConnect = hits.Count == 0;
            }

            if (shouldConnect)
            {
                target.SetEdge(nodeA, nodeB);
            }
        }
コード例 #5
0
        public int IsItemInRange()
        {
            //print("IsItemInRange()");

            var nodesWithItems = new List <MBGraphNode>();

            // Check all reachable nodes to see if it contains a PowerUp
            foreach (var nodeID in reachableNodeIds)
            {
                var node = GameplayManager.Instance.gridGraph.graph[nodeID];

                // Check if node has an ItemBox on it
                for (int i = 0; i < node.Data.transform.childCount; ++i)
                {
                    Transform child = node.Data.transform.GetChild(i);
                    if (child.gameObject.CompareTag("PowerUp"))
                    {
                        nodesWithItems.Add(GameplayManager.Instance.gridGraph.graph[nodeID].Data.GetComponent <MBGraphNode>());
                    }
                }
            }

            // At least one PowerUp is in Range
            if (nodesWithItems.Count > 0)
            {
                var shortestDistance = int.MaxValue;
                var closestNode      = nodesWithItems[0];

                // Find the closest PowerUp
                foreach (var node in nodesWithItems)
                {
                    List <GraphNode <GameObject> > path = pathFinding.FindPath(PositionNode.nodeId, node.nodeId, MovementHeuristic, checkpoints.Count <= 1);

                    if (path.Count < shortestDistance)
                    {
                        shortestDistance = path.Count;
                        closestNode      = node;
                    }
                }

                moveTargetNode = closestNode;
                return((int)BTNode.EState.Success);
            }

            // No Items in Range
            return((int)BTNode.EState.Failure);
        }
コード例 #6
0
        public int MoveToCover()
        {
            //print("MoveToCover()");

            // foreach player in the playerAttackThreats list, check if they have ranged/attack items
            // if they do, then foreach spot that the player can reach choose the one that is safest
            // and add the CRMove() coroutine to the queue (see below) and return success
            // else if there is no cover available then return failure

            List <MBGraphNode> coverNodes = reachableNodeIds.Select(nId => GameplayManager.Instance.gridGraph.graph[nId].Data.GetComponent <MBGraphNode>()).ToList();

            foreach (AbstractPlayer player in playerAttackThreats)
            {
                int pMissileIndex = player.Inventory.GetItemIndex("Rocket");

                if (pMissileIndex != -1)
                {
                    for (int i = 0; i < coverNodes.Count; ++i)
                    {
                        MBGraphNode node = coverNodes[i];

                        bool coverAvailable = false;

                        // check for guaranteed shield
                        PU_Base item = node.transform.GetComponentInChildren <PU_Base>();
                        if (item != null && item.powerUpScript is PU_Shield)
                        {
                            coverAvailable = true;
                            coverNodes.Clear();
                            coverNodes.Add(node);
                            break;
                        }

                        if (!coverAvailable)
                        {
                            // if we don't hit something, then there is no cover at this node and so, we remove it from the cover list
                            RaycastHit[] hits = Physics.RaycastAll(player.transform.position + (Vector3.up * 0.5f), node.transform.position - player.transform.position);
                            //Debug.DrawRay(player.transform.position, node.transform.position - player.transform.position, Color.red, 10000);

                            foreach (RaycastHit hit in hits)
                            {
                                // ignore ourselves
                                if (hit.collider.transform == transform)
                                {
                                    continue;
                                }

                                //print(node.transform.localPosition);
                                coverAvailable = true;
                                break;
                            }
                        }

                        if (!coverAvailable)
                        {
                            coverNodes.RemoveAt(i);
                            --i;
                        }
                    }
                }
            }

            if (coverNodes.Count > 0)
            {
                // Get cover node that is closest to the closest checkpoint/goal
                Checkpoint  checkpointTarget = GetClosestCheckpoint();
                MBGraphNode optimalCoverNode = checkpointTarget == null ? coverNodes[0] : checkpointTarget.node;

                if (checkpointTarget != null)
                {
                    float coverToCPDist = Mathf.Infinity;
                    foreach (MBGraphNode coverNode in coverNodes)
                    {
                        float tempDist = (coverNode.transform.position - checkpointTarget.transform.position).magnitude;
                        if (tempDist < coverToCPDist)
                        {
                            optimalCoverNode = coverNode;
                            coverToCPDist    = tempDist;
                        }
                    }
                }

                List <GraphNode <GameObject> > path = pathFinding.FindPath(PositionNode.nodeId, optimalCoverNode.nodeId, MovementHeuristic, checkpoints.Count <= 1);

                if (path.Count > 0)
                {
                    path.RemoveAt(0);
                }
                if (path.Count == 0)
                {
                    return((int)BTNode.EState.Failure);
                }

                Move(path);

                return((int)BTNode.EState.Success);
            }
            else
            {
                return((int)BTNode.EState.Failure);
            }
        }
コード例 #7
0
        public int ShouldUseItem()
        {
            //print("ShouldUseItem()");

            // TODO: foreach item in inventory,
            //       if any item would give the player any value
            //           set itemToUseIndex to be the item that offers the greatest value and return success
            //       else if none of the items give any value at this moment (ex: no targets, etc...)
            //           return failure

            int missileIndex  = Inventory.GetItemIndex("Rocket");
            int boostIndex    = Inventory.GetItemIndex("Boost");
            int shieldIndex   = Inventory.GetItemIndex("Shield");
            int oilSpillIndex = Inventory.GetItemIndex("Oil Spill");

            if (boostIndex != -1)
            {
                itemToUseIndex = boostIndex;
            }
            else if (missileIndex != -1)
            {
                // check if other players are in sight for missile target
                foreach (AbstractPlayer p in GameplayManager.Instance.Players)
                {
                    RaycastHit[] hits = Physics.RaycastAll(transform.position + (Vector3.up * 0.5f), p.transform.position - transform.position);
                    foreach (RaycastHit hit in hits)
                    {
                        // we are colliding with ourself
                        if (hit.transform == transform)
                        {
                            continue;
                        }

                        if (hit.collider.tag.Equals("HumanPlayer") || hit.collider.tag.Equals("AIPlayer"))
                        {
                            AbstractPlayer potentialTarget = hit.collider.GetComponent <AbstractPlayer>();

                            // check if potentialTarget is in equal or higher place standing. If not, then do not waste the missile on them.
                            if (potentialTarget.checkpoints.Count <= checkpoints.Count)
                            {
                                playerAttackTarget = potentialTarget;
                                itemToUseIndex     = missileIndex;
                            }

                            break;
                        }
                    }
                }
            }
            else if (shieldIndex != -1)
            {
                // check if player is in sight for foreign missiles
                foreach (AbstractPlayer p in GameplayManager.Instance.Players)
                {
                    if (p.Inventory.GetItemIndex("Rocket") != -1)
                    {
                        RaycastHit[] hits = Physics.RaycastAll(p.transform.position + (Vector3.up * 0.5f), transform.position - p.transform.position);
                        Debug.DrawRay(p.transform.position, transform.position - p.transform.position, Color.red, 10000);
                        foreach (RaycastHit hit in hits)
                        {
                            // the ray has hit us
                            if (hit.transform == transform)
                            {
                                itemToUseIndex = shieldIndex;
                            }
                        }

                        // itemToUseIndex = shieldIndex;
                    }
                }
            }
            else if (oilSpillIndex != -1)
            {
                // we can only place oil spills on neighbor nodes around us
                IWeightedDiGraph <GameObject, float> graph = PositionNode.mbGraph.graph;
                List <GameObject> potentialOilTargets      = new List <GameObject>();
                foreach (GraphNode <GameObject> graphNode in graph.Neighbors(PositionNode.nodeId))
                {
                    // CalculatePathToGoal() and if this node is on that path then do not add it to the list (otherwise we'd be hindering ourselves)
                    potentialOilTargets.Add(graphNode.Data);
                }

                Checkpoint  checkpointTarget = GetClosestCheckpoint();
                MBGraphNode checkpointNode   = checkpointTarget == null ? null : checkpointTarget.node;

                GraphNode <GameObject> optimalGraphNode = reachableNodeIds.Count > 0 ? GameplayManager.Instance.gridGraph.graph[reachableNodeIds[0]] : null;
                float dist = Mathf.Infinity;
                foreach (string nodeId in reachableNodeIds)
                {
                    GraphNode <GameObject> gNode = GameplayManager.Instance.gridGraph.graph[nodeId];
                    float tempDist = (gNode.Data.transform.position - checkpointNode.transform.position).magnitude;
                    if (tempDist < dist)
                    {
                        optimalGraphNode = gNode;
                        dist             = tempDist;
                    }
                }

                if (optimalGraphNode != null)
                {
                    List <GraphNode <GameObject> > path = pathFinding.FindPath(PositionNode.nodeId, optimalGraphNode.Id, MovementHeuristic, checkpoints.Count <= 1);

                    if (path.Count > 0)
                    {
                        path.RemoveAt(0);
                    }
                    if (path.Count == 0)
                    {
                        return((int)BTNode.EState.Failure);
                    }


                    // If there 1 or less nodes that don't have an oil spill on them then don't place the oil spill or else we would be trapping ourselves
                    if (potentialOilTargets.Count > 1)
                    {
                        // select the first potential oil target
                        nodeToSpillOn = potentialOilTargets[0];
                        foreach (GameObject ot in potentialOilTargets)
                        {
                            if (!path.Contains(GameplayManager.Instance.gridGraph.graph[ot.GetComponent <MBGraphNode>().nodeId]))
                            {
                                nodeToSpillOn  = ot;
                                itemToUseIndex = oilSpillIndex;
                                break;
                            }
                        }
                    }
                }
            }

            return(itemToUseIndex >= 0 ? (int)BTNode.EState.Success : (int)BTNode.EState.Failure);
        }
コード例 #8
0
        protected void DrawControls()
        {
            MBGraphNode target = (MBGraphNode)this.target;

            EditorGUILayout.Space();

            List <MBGraphNode> selectedNodes = new List <MBGraphNode>();

            foreach (GameObject obj in Selection.gameObjects)
            {
                if (obj.GetComponent <MBGraphNode>() != null)
                {
                    selectedNodes.Add(obj.GetComponent <MBGraphNode>());
                }
            }

            if (selectedNodes.Count == 1)
            {
                // A single node is selected
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                {
                    if (GUILayout.Button("Add Node"))
                    {
                        GameObject addedNode = null;
                        if (addNodeEdgeDirectionality == 2)
                        {
                            addedNode = target.mbGraph.AddNode();
                        }
                        else
                        {
                            addedNode = target.mbGraph.AddNode(target, addNodeEdgeWeight, (EdgeDirectionality)addNodeEdgeDirectionality);
                        }

                        Selection.activeGameObject = addedNode;
                    }

                    addNodeEdgeDirectionality   = EditorGUILayout.Popup("Edge Directionality", addNodeEdgeDirectionality, strEdgeDirectionalities);
                    addNodeEdgeWeightIsDistance = EditorGUILayout.Toggle("Weight == Distance", addNodeEdgeWeightIsDistance);
                    addNodeEdgeWeight           = EditorGUILayout.FloatField("Edge Weight", addNodeEdgeWeight);
                }
                EditorGUILayout.EndVertical();
            }
            else if (selectedNodes.Count == 2)
            {
                // A pair of nodes (edge) has been selected
                GraphEdge <float>[] modifiableEdges = new GraphEdge <float> [2];
                modifiableEdges[0] = target.mbGraph.graph.GetEdge(selectedNodes[0].nodeId, selectedNodes[1].nodeId);
                modifiableEdges[1] = target.mbGraph.graph.GetEdge(selectedNodes[1].nodeId, selectedNodes[0].nodeId);

                for (int i = 0; i < modifiableEdges.Length; ++i)
                {
                    GraphEdge <float> edge = modifiableEdges[i];

                    EditorGUILayout.BeginVertical(EditorStyles.helpBox);

                    var edgeLabelStyle = new GUIStyle(GUI.skin.label)
                    {
                        fontStyle = FontStyle.Bold
                    };
                    EditorGUILayout.LabelField(i == 0 ? "A -> B" : "B -> A", edgeLabelStyle);
                    DrawHorizontalLine();

                    int   edgeDirectionalityInt = EditorGUILayout.Popup("Directionality", edge == null ? 2 : (int)edge.Directionality, strEdgeDirectionalities);
                    float edgeWeight            = EditorGUILayout.FloatField("Edge Weight", edge == null ? 0 : edge.Weight);
                    bool  edgeWeightIsDistance  = GUILayout.Button("Weight == Distance");

                    EditorGUILayout.EndVertical();

                    if (
                        (edge != null || edgeDirectionalityInt != 2) &&
                        ((edge == null && edgeDirectionalityInt != 2) || edgeWeight != edge.Weight || edgeDirectionalityInt != (int)edge.Directionality)
                        )
                    {
                        if (edge != null && edgeDirectionalityInt == 2)
                        {
                            target.mbGraph.RemoveEdge(edge.FromId, edge.ToId);
                        }
                        else if (edgeDirectionalityInt != 2)
                        {
                            if (i == 0)
                            {
                                target.mbGraph.SetEdge(selectedNodes[0], selectedNodes[1], edgeWeight, (EdgeDirectionality)edgeDirectionalityInt);
                            }
                            else if (i == 1)
                            {
                                target.mbGraph.SetEdge(selectedNodes[1], selectedNodes[0], edgeWeight, (EdgeDirectionality)edgeDirectionalityInt);
                            }
                        }

                        EditorSceneManager.MarkSceneDirty(target.gameObject.scene);
                        EditorUtility.SetDirty(target);
                    }

                    if (edgeWeightIsDistance)
                    {
                        target.mbGraph.graph.isDirty = true;
                        edge.Weight = (selectedNodes[0].transform.position - selectedNodes[1].transform.position).magnitude;
                        EditorSceneManager.MarkSceneDirty(target.gameObject.scene);
                        EditorUtility.SetDirty(target);
                    }

                    if (edgeDirectionalityInt == 0)
                    {
                        break;
                    }
                }
            }
        }
コード例 #9
0
        /// <summary>
        /// Show the available neighbors to travel to.
        /// </summary>
        /// <param name="show"></param> Whether to show the tiles or not.
        /// <param name="startNode"></param> Which node to start from.
        /// <param name="times"></param> Number of levels to find the neighbors.
        /// <param name="direction"></param> Which direction the neighbors are in.
        private void ShowMovementTiles(bool show, MBGraphNode startNode, int times, Direction direction, List <MBGraphNode> directionTiles)
        {
            if (times <= 0)
            {
                return;
            }

            for (int i = 0; i < startNode.transform.childCount; ++i)
            {
                if (startNode.transform.GetChild(i).tag.Equals("GridSquare"))
                {
                    startNode.transform.GetChild(i).gameObject.SetActive(show);
                }
            }

            var nodeNeighbors = startNode.mbGraph.graph.Neighbors(startNode.nodeId);

            foreach (var node in nodeNeighbors)
            {
                int extraValue = (node.Data.transform.GetComponentInChildren <OilSpillManager>()) != null ? 2 : 0;

                var mbNode = node.Data.GetComponent <MBGraphNode>();

                bool doIt = true;
                if (GameplayManager.Instance.blockedOffNodes.Contains(mbNode) && player.checkpoints.Count > 1)
                {
                    doIt = false;
                }

                if (node.Data.transform.position.x > startNode.transform.position.x && direction == Direction.Right)
                {
                    if (doIt)
                    {
                        directionTiles.Add(mbNode);
                        ShowMovementTiles(show, mbNode, times - 1 - extraValue, Direction.Right, directionTiles);
                    }
                }
                if (node.Data.transform.position.x < startNode.transform.position.x && direction == Direction.Left)
                {
                    if (doIt)
                    {
                        directionTiles.Add(mbNode);
                        ShowMovementTiles(show, mbNode, times - 1 - extraValue, Direction.Left, directionTiles);
                    }
                }
                if (node.Data.transform.position.z > startNode.transform.position.z && direction == Direction.Down)
                {
                    if (doIt)
                    {
                        directionTiles.Add(mbNode);
                        ShowMovementTiles(show, mbNode, times - 1 - extraValue, Direction.Down, directionTiles);
                    }
                }
                if (node.Data.transform.position.z < startNode.transform.position.z && direction == Direction.Up)
                {
                    if (doIt)
                    {
                        directionTiles.Add(mbNode);
                        ShowMovementTiles(show, mbNode, times - 1 - extraValue, Direction.Up, directionTiles);
                    }
                }
            }
        }
コード例 #10
0
        private void GenerateGrid(MBGraph target)
        {
            ClearNodes(target);

            float   width    = target.__gridColumns * target.__gridCellSize;
            float   height   = target.__gridRows * target.__gridCellSize;
            Vector3 position = new Vector3(target.transform.position.x - (width / 2), target.transform.position.y, target.transform.position.z - (height / 2));

            // 1st pass: generate nodes
            MBGraphNode[,] nodeGrid = new MBGraphNode[target.__gridRows, target.__gridColumns];
            for (int r = 0; r < target.__gridRows; ++r)
            {
                float startingX = position.x;
                for (int c = 0; c < target.__gridColumns; ++c)
                {
                    bool shouldAddNode = true;
                    if (target.__detectCollisions)
                    {
                        List <Collider> colliders = FilterColliders(target, Physics.OverlapSphere(position, target.__collisionRadius));
                        shouldAddNode = colliders.Count == 0;
                    }

                    if (shouldAddNode)
                    {
                        GameObject addedNodeObj = target.AddNode();
                        addedNodeObj.transform.position = position;
                        nodeGrid[r, c] = addedNodeObj.GetComponent <MBGraphNode>();
                    }

                    position = new Vector3(position.x + target.__gridCellSize, position.y, position.z);
                }
                position = new Vector3(startingX, position.y, position.z + target.__gridCellSize);
            }

            // 2nd pass: generate edges
            for (int r = 0; r < target.__gridRows; ++r)
            {
                for (int c = 0; c < target.__gridColumns; ++c)
                {
                    if (nodeGrid[r, c] == null)
                    {
                        continue;
                    }

                    // NWES edges
                    if (c > 0 && nodeGrid[r, c - 1] != null)
                    {
                        ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r, c - 1]);
                    }
                    if (c < target.__gridColumns - 1 && nodeGrid[r, c + 1] != null)
                    {
                        ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r, c + 1]);
                    }
                    if (r > 0 && nodeGrid[r - 1, c] != null)
                    {
                        ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r - 1, c]);
                    }
                    if (r < target.__gridRows - 1 && nodeGrid[r + 1, c] != null)
                    {
                        ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r + 1, c]);
                    }

                    // diagonal edges
                    if (target.__gridType == MBGraph.EGridType.EightWay)
                    {
                        if (r > 0 && c > 0 && nodeGrid[r - 1, c - 1] != null)
                        {
                            ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r - 1, c - 1]);
                        }
                        if (r < target.__gridRows - 1 && c < target.__gridColumns - 1 && nodeGrid[r + 1, c + 1] != null)
                        {
                            ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r + 1, c + 1]);
                        }
                        if (r > 0 && c < target.__gridColumns - 1 && nodeGrid[r - 1, c + 1] != null)
                        {
                            ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r - 1, c + 1]);
                        }
                        if (r < target.__gridRows - 1 && c > 0 && nodeGrid[r + 1, c - 1] != null)
                        {
                            ConnectGridNodes(target, nodeGrid[r, c], nodeGrid[r + 1, c - 1]);
                        }
                    }
                }
            }
        }