Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
1
Question by Alphapieter1 · Feb 17, 2016 at 01:24 PM · c#scripting problemmovementgrid

Hexagonal Grid Rangefinding

I am trying to develop an hexagonal turnbased strategy game and moving the units is giving me real trouble. Basicly what i want my programm to do is if u select an units all tiles that it can move to are higlited and once you moved it the tiles return to normal. The thing is that i have tyles that are inaccesabel and tiles that are harder to pass than others. like an forresttile takes two moventpoints, an grasstile takes one and mountains are inaccesabel. but if there is an gap between two mountains the unit must be able to drive trough it and then left and right.

So i developed an algorythmen which das the folloing things:

check all tiles in an straight line in all six directions if they are accesabel once the first tile isnt accesabel (mountain or all movepoints are used) stop the loop, for evry accesabel tile

check all tiles in an straight line in all six directions if they are accesabel once the first tile isnt accesabel (mountain or all movepoints are used) stop the loop, for evry accesabel tile

check all tiles in an straight line in all six directions if they are accesabel once the first tile isnt accesabel (mountain or all movepoints are used) stop the loop, for evry accesabel tile

. . .

this kinda works but it is not very fast and it can only change the direction as often as i reapet the code(in this case three times) and my fastest unit can move up to 18 tiles and i have to assume that it may has to change direction evry tile. due to the fact that more often an unit rotates, the more possible ways it can go, the more tiles are chequed, number of chequed tiles grows exponetial with evry time i repeat the code. This algorhytmen would check for an unit that can move 18 tiles and possible change direction on evry tile around

(6x18)x(6x17)x(6x16)x(6x15)x(6x14)x(6x13)x(6x12)x(6x11)x(6x10)x(6x9)x(6x8)x(6x7)x(6x6)x(6x5)x(6x4)x(6x3)x(6x2)x6 =650224796128741650855886848000 tiles

in the end it would return the right range the unit can move but it would take an ridicules amount of time. There must be an better way to do this. I am not asking for any code but an idea how to solve this would be nice. Thx alot for any advice you might be able to give me.

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Cherno · Feb 17, 2016 at 02:14 PM 0
Share

Looks into A* Pathfinding algorithms. If you want a complete A* solution, check Aron Granberg's Astar Pathfinding Project.

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Feb 17, 2016 at 02:17 PM

Well, since you have a dynamic environment there's no way around checking each tile until you run out of movement points. However i would suggest to use a similar apporach to "A*", just that you don't have an actual target. So you would simply add your starting tile to an "open" list. When a tile is expanded you check all 6 neighbor tiles and add them to the open list. Once a tile is expanded you remove it from the openlist and add it to a "closed" list.

When checking the neighbor tiles you don't readd a tile that is already on the closed list. It's important that you sort your openlist by the "left over movement points" so that the tile with the most movement points left should be processed first. That ensures that you get the "best" way to each tile. For each tile you should save the remaining movement points, so when expanding to a neighbor you use that value as reference. The start tile should be initialized with your available movement points.

edit

Since we don't know how your grid data is actually stored we can only provide abstract pseudo code.

 List<Tile> GetNeighbors(Tile) // should return all 6 neighbors of the given tile.
 float GetCost(Tile) // should return the cost of that tile.
 
 List<Tile> openList = new List<Tile>();
 List<Tile> closedList = new List<Tile>();
 Dictionary<Tile, float> movementPoints = new Dictionary<Tile, float>();

 void ExpandTile(Tile aTile)
 {
     float parentPoints = movementPoints[aTile];
     closedList.Add(aTile);
     foreach (var tile in GetNeighbors(aTile))
     {
         if (closedList.Contains(tile) || openList.Contains(tile))
             continue;
         float points = parentPoints - GetCost(tile);
         if (points < 0)
         {
             // this tile is outside of the reachable area
             continue;
         }
         openList.Add(tile);
         movementPoints[tile] = points;
     }
 }

 void CalcRange(Tile aStartingTile, float aMovementPoints)
 {
     openList.Clear();
     closedList.Clear();
     movementPoints[aStartingTile] = aMovementPoints;
     ExpandTile(aStartingTile);
     while (openList.Count > 0)
     {
         openList.Sort((a,b)=> movementPoints[a].CompareTo(movementPoints[b]) );
         var tile = openList[openList.Count - 1];
         openList.RemoveAt(openList.Count - 1);
         ExpandTile(tile);
     }
 }

I've tested this with a normal x / y grid and it works as expected:

I added a "virtual" obstacle(cost >5000) on the lower left side and a "light" obstacle on the top left side (cost "3" instead of "1").

The yellow cubes are the grid positions that are outside the reachable area. The red cubes are the 5000+ obstacle and the rest are the movable tiles with a color faded according to their remaining movement points.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Feb 17, 2016 at 04:00 PM 0
Share

Note: This approach isn't optimised in any way. If your "tile" class can hold the remaining points directly it gets way more effecient as you don't need the dictionary. Also the openlist could be implemented with a binary heap or something similar. Also when you are in some sort of grid, there's no need for a GetNeighbors method that creates a List since you usually can simply calculate the neighbor tiles from the current tiles position.

Also the closedList might be implemented with a Dictionary ins$$anonymous$$d of a list if you have great distances and therefore alot of tiles involved. The closedList could also be implemented implicitly with a simple boolean value inside the tile class.

However that all depends on the actual datatypes and grid structures used. Like "A*" this approach would work with any kind of grid / node-graph.

avatar image Alphapieter1 · Feb 17, 2016 at 06:00 PM 0
Share

Thank you a lot ill try it out.

avatar image Alphapieter1 · Feb 19, 2016 at 06:52 PM 0
Share

it worked thank you alot

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How can I make the camera not overreach a limit of rotation one axis. 0 Answers

Using spawners script variable to set relevant speed of an Enemy... Im bewildered 1 Answer

Animation/Movement Error 1 Answer

How can I make the character jump between the boxes? 0 Answers

Player not moving in the right direction instantly 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges