Search code examples
c#unity-game-enginefor-loopforeach2d

Unity 2D - How to make a movement point system in a map based on non-gridded tiles?


I'm making a wargame set on a map in which the player's divisions move across irregular-shaped provinces (a la Paradox) in a turn-based manner. I want to make it so that each turn, the divisions can move an amount of provinces equal to the division's movement points (by default 2).

I'm having trouble (mainly because im a newbie) coding a way for the game to detect which provinces are in range to a division, aside from the ones directly adjacent to the division's current position. Whatever I do, the game either detects all provinces as "in-range" or just doesn't make an accurate calculation.

The provinces are not in a grid system because of their irregular shapes, so I'm using collider overlaps to detect which ones are next to each other. Feel free to tell me if there's a better way to do it.

Here's what I tried (skip to GetTilesInRange):

{ 
    
    private void Awake()
    {
        Army = GameObject.FindGameObjectsWithTag("Division");   
        Map = GameObject.FindGameObjectsWithTag("Tile");
        DivisionHeightOffset = new Vector3(0f, -ñDivisionHeightOffsetY, 0f);
        
        
    }
    
    private void Update()
    {
       mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
       CheckforSelectedDivisions();       
    }


    private void CheckforSelectedDivisions()    
    {             
      foreach ( GameObject Division in Army)
      {          
        if (Division.GetComponent<DivisionBehaviour>().Selected && !Checked) 
        {                       
          Checked = true;
          SelectedDivision = Division;
          SelectedDivisionPosition = Division.transform.position;
          NameOfSelectedDivision = Division.name;
          DivisionOverlapPoint = Division.transform.position + DivisionHeightOffset; 
          
          DivisionMovementPoints = (Division.GetComponent<DivisionBehaviour>().MovementPoints);
          GetCurrentTile();                                     
        }          
      }
      if(SelectedDivision != null) { if(!SelectedDivision.GetComponent<DivisionBehaviour>().Selected) {Checked = false;}}
    }

    private void GetCurrentTile()
    {
        
        foreach (GameObject Tile in Map) if (Tile.GetComponent<Collider2D>())
        {           
           if(Tile.GetComponent<Collider2D>().OverlapPoint(DivisionOverlapPoint))
           {              
              CurrentTile = Tile;              
              Debug.Log(NameOfSelectedDivision + " is in " + CurrentTile.name);
              CurrentTilePosition = Tile.transform.position;
              CurrentTileBounds = Tile.GetComponent<Collider2D>().bounds;
              GetTilesInRange();
           }      
        }
    }

  **  private void GetTilesInRange()
    {                                       
       i = DivisionMovementPoints;

        
        foreach (GameObject TileB in Map) if (TileB.GetComponent<Collider2D>() && TileB != CurrentTile && !TileB.GetComponent<TileInfo>().Movable && !TileB.GetComponent<TileInfo>().Movable2)
        {
        
             
             if(TileB.GetComponent<Collider2D>().bounds.Intersects(CurrentTileBounds))
             {
                  
               MovableTile = TileB;
               Debug.Log(MovableTile.name + " is in range!");

                    
                            
             }**

             else if(i > 0 && TileB.GetComponent<Collider2D>().bounds.Intersects(MovableTile.GetComponent<Collider2D>().bounds))
             {
                  
                    i = i - 1;
                  MovableTile = TileB;
                  Debug.Log(MovableTile.name + " is in range!");
             }

        }


       
    }

    

    
      
    
    





}
    

Solution

  • Have navigation info outside of graphical info. You will probably need to store other data on provinces as well, like production, who owns etc.

    public class Province    // Class to hold province data
    {
        public int ProvinceID;                          // Pointer to Building Type
        public string Name;                              // Name of Province          
        public string Spritename;                     // Sprite to show capital building
        public int BuildingFlags;                      // Flags for the Province
        public List<int> AdjacentProvinces;     // List of adjacent Province IDs 
        public GameObject GO;                       // Game Object Province sprite
    
    }
    

    You can search each province for neighbors going through the list of its public List AdjacentProvinces;

    You could write a function to return a list of adjacent neighbors.

    You could then call this function of each of its adjacent neighobors for each 1 movement step you want to add to see if an Province ID is in range