// ------------------------------------------------------------------------------------------------------------
    #region update/ input

    protected void Update()
    {
        if (Input.GetMouseButtonDown(0) && GUIUtility.hotControl == 0 && unitMoving == false)
        {
            // Check what the player clicked on. I've set Tiles to be on Layer 8 and Unit on Layer 9.
            // Each tile has its own collider attached but I could have used a big invisible collider
            // that stretches the whole map as a catch all for clicks that did not fall on a unit.
            // The only reason the tiles each have a collider is because they are used in other
            // samples too that requires it.

            RaycastHit hit;
            Ray        r = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(r, out hit, Mathf.Infinity, clickMask))
            {
                if (hit.transform.gameObject.layer == 8)
                {
                    // a tile was clicked
                    Sample4Tile n = map.NodeAtWorldPosition <Sample4Tile>(hit.point);
                    //Sample4Tile n = (Sample4Tile)map.NodeAtWorldPosition(hit.point);
                    if (n != null)
                    {
                        Debug.Log("Clicked on: " + n.tileName);

                        // check if a tile that the active unit may move to
                        if (activeUnit != null && validMoveNodes.Contains(n))
                        {
                            // get the path
                            List <MapNavNode> path = map.Path <MapNavNode>(activeUnit.tile, n, OnNodeCostCallback);
                            if (path != null)
                            {
                                unitMoving = true;                                 // need to wait while unit is moving
                                ClearMoveMarkers();
                                activeUnit.Move(path, OnUnitMoveComplete);
                            }
                        }
                    }
                }
                else
                {
                    // a unit was clicked. first clear the previously selected unit
                    if (activeUnit != null)
                    {
                        activeUnit.UnitDeSelected();
                        ClearMoveMarkers();
                    }

                    activeUnit = hit.transform.GetComponent <Sample4Unit>();
                    if (activeUnit != null)
                    {
                        // tell the unit it was selected so that it can change colour
                        activeUnit.UnitSelected();

                        // show the player the area that the unit may move to
                        UpdateMoveMarkers();
                    }
                }
            }
        }
    }
Example #2
0
    /// <summary>
    /// I override this callback so that I can respond on the grid being
    /// changed and place/ update the actual tile objects
    /// </summary>
    public override void OnGridChanged(bool created)
    {
        // The parent object that will hold all the instantiated tile objects
        Transform parent = gameObject.transform;

        // Remove existing tiles and place new ones if map was (re)created
        // since the number of tiles might be different now
        if (created)
        {
            for (int i = parent.childCount - 1; i >= 0; i--)
            {
                // was called from editor
                Object.DestroyImmediate(parent.GetChild(i).gameObject);
            }

            // Place tiles according to the generated grid
            for (int idx = 0; idx < grid.Length; idx++)
            {
                // make sure it is a valid node before placing tile here
                if (false == grid[idx].isValid)
                {
                    continue;
                }

                // create the visual tile
                GameObject go = (GameObject)Instantiate(tileFab);
                go.name  = "Tile " + idx.ToString();
                go.layer = tileLayer;                 // set the layer since I will need it in Sample4Controller to check what the player clicked on
                go.transform.position = grid[idx].position;
                go.transform.parent   = parent;

                // MapNav created the node as the custom Sample4Tile type
                // Now init the tileName property in it
                Sample4Tile node = grid[idx] as Sample4Tile;
                node.tileName = go.name;
                node.tileObj  = go;
            }
        }

        // else, simply update the position of existing tiles
        else
        {
            for (int idx = 0; idx < grid.Length; idx++)
            {
                // make sure it is a valid node before processing it
                if (false == grid[idx].isValid)
                {
                    continue;
                }

                // Since I gave the tiles proper names I can easily find them by name
                GameObject go = parent.Find("Tile " + idx.ToString()).gameObject;
                go.transform.position = grid[idx].position;
            }
        }
    }
    protected bool unitMoving = false;                          // set when a unit is moving and no input should be accepted

    #endregion
    // ------------------------------------------------------------------------------------------------------------
    #region start

    protected void Start()
    {
        // get reference to the mapnav map
        map = GameObject.Find("Map").GetComponent <Sample4Map>();

        // also used in sample4b
        if (map == null)
        {
            map = GameObject.Find("Map").GetComponent <Sample4bMap>();
        }

        // in this sample I will simply spawn 10 units on random locations of the map
        for (int i = 0; i < 10; i++)
        {
            Sample4Tile selectedTile = null;

            // find a tile to place the unit on. I will randomly select one.
            // but I need to check if there is not already a unit on the
            // selected tile before accepting it.
            while (true)
            {
                int idx = Random.Range(0, map.grid.Length);

                // make sure this is a valid node
                if (map.ValidIDX(idx))
                {
                    // now check if there is not already a unit on it
                    selectedTile = map.grid[idx] as Sample4Tile;
                    if (selectedTile.unit == null)
                    {
                        // no unit on it, lets use it
                        break;
                    }
                }
            }

            // create the unit and place it on the tile
            GameObject go = (GameObject)Instantiate(unitFab);
            go.transform.position = selectedTile.position;
            go.layer = 9;             // in this sample Units must be in layer 9

            // be sure to tell the tile that this Unit is on it
            Sample4Unit unit = go.GetComponent <Sample4Unit>();
            unit.Resetunit();            // reset its moves now too
            unit.LinkWithTile(selectedTile);
            units.Add(unit);             // keep a list of all units for quick access
        }
    }
Example #4
0
    /// <summary>
    /// I use this to link the tile and unit with each other so that the
    /// tile and unit knows which unit is on the tile. I will pass null
    /// to simply unlink the tile and unit.
    /// </summary>
    public void LinkWithTile(Sample4Tile t)
    {
        // first unlink the unit from the tile
        if (tile != null)
        {
            tile.unit = null;
        }
        tile = t;

        // if t == null then this was simply an unlink and it ends here
        if (tile == null)
        {
            return;
        }

        // else tell the tile that this unit is on it
        tile.unit = this;
    }
    private bool CheckIfValidNode(MapNavNode toNode)
    {
        Sample4Tile n = toNode as Sample4Tile;

        // this will help prevent a border being drawn around the active unit's tile
        // also see the IF(neighbours[j] != activeUnit.tile ...) that must be used above
        if (n == activeUnit.tile)
        {
            return(true);
        }

        // can't move to a tile that has a unit on it
        if (n.unit != null)
        {
            return(false);
        }

        // finally, return tile's default state
        return(toNode.isValid);
    }