Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Tile Based Map Nav

Discussion in 'Assets and Asset Store' started by Leslie-Young, Jun 2, 2012.

  1. TCGMabe

    TCGMabe

    Joined:
    Jun 12, 2013
    Posts:
    3
    @c-Row Thank you for the quick response and the clear answer. I assumed it would work but have not had an opportunity to give it a try.

    @Leslie Young, I guess I was imagining that I could lay out a level using UniRPG and then create a Map Nav to handle movement similar to your dungeon example .... Is this possible ?
     
    Last edited: Jun 25, 2013
  2. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Yes, you can do that. They just do not talk to each other.For example, the tiles you place with Tile Ed. will not automatically create Nodes that can be used by MapNav.
     
  3. TCGMabe

    TCGMabe

    Joined:
    Jun 12, 2013
    Posts:
    3
    Perfect ... That's what I was hoping to find out when I bought them ! Now go finish building some more awesome tools !
     
  4. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    Leslie,

    I'm having an issue with the package with a unit being hidden by part of the terrain. I have AdjustToNormals and AdjustToCollider turned on, but nothing seems to help.
    $Issue.png

    Thanks.
     
  5. The Ghost

    The Ghost

    Joined:
    Jul 7, 2012
    Posts:
    188
    I wish I wasn't so poor and creditcardless, I would buy this in a heartbeat.
     
  6. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Is the Unit's collider big enough, and is the terrain's layer set to whatever you set "adjustment layer mask" to in the Unit's inspector?
     
  7. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    I'm using a Box Collider and I set the XYZ size all to 2 and it did not make a difference.
    Both the Adjustment Layer Mask and the Terrain's layer are set to a layer I called "Terrain".
    Neither the unit nor the terrain have the "Trigger" set to true in their collider.
    I tried to assign both the unit and terrain a physic material, but that did not make a difference.

    Is it because I created the Terrain within unity instead of importing a FBX model for the terrain?
    --EDIT--
    I answered my own question above - it doesn't seem to make a difference where the terrain comes from. I was able to reproduce the effect in one of the included examples by changing the scale of the land_unit to 4, 0.2, 2 respectively - this matches the scale I am using in my project.

    $Issue2.png


    --2ND EDIT--
    I think the issue lies in the _UpdateUnitNormal() function. It looks like it calculates the adjustment to the position based on the center position of the object ( _tr.position ). I don't know enough about Unity yet to know if it is possible to compute the adjustment for each of the 4 corners of a cube(instead of the center) to prevent any of it from being obscured by the terrain layer.
     
    Last edited: Jul 1, 2013
  8. MRDarius

    MRDarius

    Joined:
    Jul 1, 2013
    Posts:
    2
    I have a Question.
    I use New MapNav
    It is not possible that make 10*10 map.
    Only one is maked.
    Why?

    $aaa.png $bbb.png
     
  9. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    So your Unit is too big and should rather be checked from the 4 corners than the center? Doing the test should be possible, placing the unit unit correctly from that info I'm not too sure about.

    With the height test I can place the unit higher or lower, so now I would have 4 points of different height and would probably need some kind of average which could still cause the unit to stick through terrain. To remedy this you could make it that the unit follow the terrain normal, but which normal? Do I only use the center for this? Again the unit might stick through terrain areas.

    I'll have to look into this and get back to you.
     
  10. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    @MRDarius, there should not be a reason for it to fail if everything is setup correctly. Did you test with a default node perfab 1st to see if that works? They are under, \Assets\Tile Based Map and Nav\Prefabs\tile_nodes\

    When creating a new node you should make sure it is similar to those.

    Also, any red error messages in your unity console? That is the first thing to check and sort out if anything goes wrong. Please post the full error message here if there is one.
     
  11. MRDarius

    MRDarius

    Joined:
    Jul 1, 2013
    Posts:
    2
    OK!
    It is Very Important!

    "\Assets\Tile Based Map and Nav\Prefabs\tile_nodes"
     
  12. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    @csshelton70, This is the best I could come up with. I think you should 1st look at making your terrain work better with your units. Don't create too sharp angles for example.

    You can try the "average" or "max height" code and see which works best. The angle that the unit should sit as is still calculated in the old way and uses the centre to figure out what the terrain normal is to align to. I can't think of any other way to decide what this angle should be.

    Code (csharp):
    1. protected void _UpdateUnitNormal()
    2. {
    3.     if ( (!adjustNormals  !adjustToCollider) || adjustmentLayerMask==0 ) return;
    4.  
    5.     //Vector3 pos = _tr.position; pos.y += 10f;
    6.     //RaycastHit hit;
    7.     //if (Physics.Raycast(pos, -Vector3.up, out hit, 50f, adjustmentLayerMask))
    8.     //{
    9.     //  pos.y -= hit.distance;
    10.     //  _tr.position = pos;
    11.  
    12.     //  if (adjustNormals)
    13.     //  {
    14.     //      _smoothedNormal = Vector3.Lerp(_smoothedNormal, hit.normal, 10f * Time.deltaTime);
    15.     //      Quaternion tilt = Quaternion.FromToRotation(Vector3.up, _smoothedNormal);
    16.     //      transform.rotation = tilt * Quaternion.Euler(0f, transform.rotation.eulerAngles.y, 0f);
    17.     //  }
    18.     //}
    19.  
    20.     // *******************************************************************************
    21.     // the other method of doing this, using 4 points of box collider for height check
    22.  
    23.     BoxCollider coll = gameObject.GetComponent<BoxCollider>();
    24.     Vector3[] hitPoints = new Vector3[4];
    25.  
    26.     Vector3 pos = _tr.position + coll.center; pos.y += 10f;
    27.     pos.x += (coll.size.x * 0.5f);
    28.     pos.z += (coll.size.z * 0.5f);
    29.     hitPoints[0] = GetHit(pos);
    30.  
    31.     pos = _tr.position + coll.center; pos.y += 1f;
    32.     pos.x -= (coll.size.x * 0.5f);
    33.     pos.z -= (coll.size.z * 0.5f);
    34.     hitPoints[1] = GetHit(pos);
    35.  
    36.     pos = _tr.position + coll.center; pos.y += 1f;
    37.     pos.x += (coll.size.x * 0.5f);
    38.     pos.z -= (coll.size.z * 0.5f);
    39.     hitPoints[2] = GetHit(pos);
    40.  
    41.     pos = _tr.position + coll.center; pos.y += 1f;
    42.     pos.x -= (coll.size.x * 0.5f);
    43.     pos.z += (coll.size.z * 0.5f);
    44.     hitPoints[3] = GetHit(pos);
    45.  
    46.     // ----- average
    47.     _tr.position = (hitPoints[0] + hitPoints[1] + hitPoints[2] + hitPoints[3]) / 4f;
    48.     // -----
    49.  
    50.     // ----- max height
    51.     //pos.y = Mathf.Max(hitPoints[0].y, hitPoints[1].y);
    52.     //pos.y = Mathf.Max(pos.y, hitPoints[2].y);
    53.     //pos.y = Mathf.Max(pos.y, hitPoints[3].y);
    54.     //_tr.position = new Vector3(_tr.position.x, pos.y, _tr.position.z);
    55.     // -----
    56.  
    57.     if (adjustNormals)
    58.     {
    59.         pos = _tr.position; pos.y += 10f;
    60.         RaycastHit hit;
    61.         if (Physics.Raycast(pos, -Vector3.up, out hit, 50f, adjustmentLayerMask))
    62.         {
    63.             pos.y -= hit.distance;
    64.             _smoothedNormal = Vector3.Lerp(_smoothedNormal, hit.normal, 10f * Time.deltaTime);
    65.             Quaternion tilt = Quaternion.FromToRotation(Vector3.up, _smoothedNormal);
    66.             transform.rotation = tilt * Quaternion.Euler(0f, transform.rotation.eulerAngles.y, 0f);
    67.         }
    68.     }
    69.  
    70. }
    71.  
    72. private Vector3 GetHit(Vector3 pos)
    73. {
    74.     RaycastHit hit;
    75.     if (Physics.Raycast(pos, -Vector3.up, out hit, 50f, adjustmentLayerMask)) pos.y -= hit.distance;
    76.     return pos;
    77. }
     
  13. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    Thanks Leslie. A combination of the new code above and reducing the steepness of the angle fixes 95% of the issues.
     
  14. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    Leslie,

    I have two more questions for you, both somewhat related:

    1) Is there anything in the code that keeps track of which way the unit is facing? In my game, I'm using hexagons and need to know which face of the hexagon the unit is pointed towards.

    2) Assuming that I know which way a unit is facing, is there an easy way to only set the available spaces for movement to just those spaces in the front and front/side of the unit ( basically, 3 of the six spaces ). I know I can do it by adding or subtracting x/y from the current tile node position based on the facing, but I thought you might have a neat shortcut.

    Thanks.
     
  15. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Sorry, this is not something that is supported. The unit ends up facing whatever direction it was facing when it arrived at the tile. I do not track the facing direction at all.
     
  16. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    OK. No problem I can figure out the facing based on the rotation and the second question should not be too much more difficult

    I figured out the first part and wanted to paste my code here in case anyone else needed it, I added it to the end of the _UpdateUnitNormal() function.


    Code (csharp):
    1.  
    2. int RotY = (int)_tr.rotation.eulerAngles.y;
    3.        
    4.     if (( RotY >= 10 )  ( RotY <= 50 ))
    5.     {
    6.         Facing = 1;    
    7.     }
    8.     else if (( RotY >= 70 )  ( RotY <= 110 ))
    9.     {
    10.         Facing = 2;
    11.     }
    12.     else if (( RotY >= 130 )  ( RotY <= 170 ))
    13.     {
    14.         Facing = 3;
    15.     }
    16.     else if (( RotY >= 190 )  ( RotY <= 230 ))
    17.     {
    18.         Facing = 4;
    19.     }
    20.     else if (( RotY >= 250 )  ( RotY <= 290 ))
    21.     {
    22.             Facing = 5;
    23.     }
    24.     else
    25.     {
    26.         Facing = 6;
    27.     }
     
    Last edited: Jul 7, 2013
  17. bsuponchick

    bsuponchick

    Joined:
    Jul 5, 2013
    Posts:
    2
    Hi Leslie. I apologize in advance for the following question's lack of detail. I'm brand new to Unity, and found your package last night much to my delight. I've been playing with things today and have hit a roadblock which I'm sure is probably obvious. I've based a new scene on some of your samples, but decided not to extend your controllers but rather port over and be able to modify the controller code as needed. When I play my scene, however, I cannot ever seem to get the HandleInput method's call to Physics.Raycast to ever return true. I've double and triple checked that all of my tiles are in Layer 20 and that my units are in Layer 21 as your documentation suggests. If I remove the rayMask, I get a collision with the terrain layer, but still nothing with the tile/units layers. Do you have any thoughts on where someone new to Unity might start trying to track this down?
     
  18. bsuponchick

    bsuponchick

    Joined:
    Jul 5, 2013
    Posts:
    2
    Leslie, please disregard. After several more hours of troubleshooting, I discovered a few problems in my codebase. The most glaringly obvious was a few references to the Unit class from the examples you provided, rather than my customized Unit. Once those were resolved, I also needed to enable all of the tile colliders because they were defaulted to disabled. Which led me to my final oops, I did not add a box collider to my character model. Thanks again for making this library available, I look forward to working with it.
     
  19. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    @bsuponchick, Glad you got it working.

    @csshelton70, hah, nice one, and a simple solution :D
     
  20. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    I know this is a noob question but I can't figure it out. What I think would work, does not. How can I control the placement and most importantly the direction the camera is facing when my game starts. I try to set the rotation but it seems to have no effect.
     
    Last edited: Jul 11, 2013
  21. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    If you are talking about the camera used in the example scenes then,
    Then the CamPivot object would be the "position". This is also the object following the selected unit around. You will see the actual camera object, Main Camera, is in that object. This Main Camera object handles the tilt and rotation. So simply move pivot to where you want it and then tilt/rotate the Main Camera as needed. Keep in mind that the properties entered for Camera Orbit in Main Camera will influence the rotation you set - Ymin/max and Distance.
     
  22. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    Leslie,

    Can you check this code in TileNode.cs for me. Either I don't understand it or it may be bug.

    function : public TileNode[] GetPath(TileNode fromNode, TileNode toNode, TileNode.TileType validNodesLayer)
    I'm coming into this with oneUnitPerTileOnly = false

    --snip
    Code (csharp):
    1. if (validNodesLayer > 0)
    2.                 {
    3.                     // allow only one unit per tile?
    4. // THIS NEXT BLOCK IS SKIPPED BECAUSE oneUnitPerTileOnly = false.  Works fine
    5.                     if (oneUnitPerTileOnly)
    6.                     {
    7.                         if (!oneUnitExceptionAllowMoveOver  n.units.Count > 0) continue;
    8.                     }
    9. //THIS BLOCK IS EXECUTED  - THOUGH I DON'T THINK IT SHOULD BE.  SHOULDNT THIS BE INCLUDE IN THE ABOVE IF BLOCK?
    10.                     // now check if another unit is occupying the same layer/level on the node
    11.                     if ((n.tileTypeMask  validNodesLayer) == validNodesLayer)
    12.                     {
    13.                         if (n.GetUnitInLevel(validNodesLayer) != null) continue;
    14.                     }
    15.                     // else, not a valid node
    16.                     else continue;
    17.                 }
    --snip
     
  23. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Think of it in terms of Air and Land units.

    One Unit Per Tile then means only one Unit EVER, so an Air unit can't come stand over the Land unit. It is like a short-cut to skip the rest of the checks if the map does not support more than one unit per tile.

    The next one is for a case where you can have both a land unit and an air unit on the same tile. In that case I'm checking if another unit of the same kind is not trying to occupy the same spot. So two land units can't stand on the same tile.
     
  24. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    Ok, that makes sense. In my case, I occasionally want to allow 2 land units to cross each other and it was not being allowed by the 2nd "IF" block. I don't have any air units in this game, so I just modified the code to either approve or deny based on the oneUnitPerTile value.

    Thanks for the explanation.
     
  25. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Hi, I just purchased the package and it looks really great! However, I was planning on using it on grid that are more than 256x256. It start to crawl anything larger than 100x100 even if I turn off all gizmos displays. It looks like the way you create a node for each tile is the problem. Is it possible to change the structure to have single array(grid) to represent the tiles? I'm sure it will help us to deal with large size grid. Thanks!!!
     
  26. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Sorry, this is the way Map&Nav works and that is why I've noted on the first post that this would be best suited for maps no bigger than 80x80. To change it now would mean changing the whole system.
     
  27. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Oh, I wish I knew before I made the purchase. Well, I'll think of it as a donation for a great product. I'm sure there are many more who wish the samething. If there are chances, please reconsider supporting large grid. You may sell different versions for different needs for different price.. Thanks. ^^
     
  28. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    You can contact "asset store" to request a refund, http://unity3d.com/company/contact/

    Grids seems like it might provide for the scale of grid you are looking for, https://www.assetstore.unity3d.com/#/content/9968
     
  29. ilezhnin

    ilezhnin

    Joined:
    Jul 17, 2013
    Posts:
    17
    Good afternoon. I bought Your Asset and I had a question. I would want that the grid does not respond to other sources of light. Now if they are on the map - the cells much brighter. How can this be fixed?
     
  30. travillaintim

    travillaintim

    Joined:
    May 28, 2013
    Posts:
    4
    Hi Leslie,

    I have a couple of questions before I buy this to make sure it can do what I am hoping it can.

    I am implementing a published boardgame which I have all the graphics for, legalities handled etc..Originally I created the game using the Vassal engine, which I'm quite adept with. Unfortunately it doesn't handle true game rules logic terribly well as is out of the box unless you know Java (I don't) thus to make rules logic happen required me to use a hammer to force a square through a round hole i.e it works but results are not pretty/optimum :)

    As such I am looking to other engines that are designed to do this correctly. Unity seems to be the thing everyone points at. I only understand limited JS but Ive played around a bit here and figured out how to do textures, materials basic things but I really need to move on and start getting to the meat of things, as such I found your tool. To the questions then...

    The maps I have are 15x10. When I create this with TMN is there a way to "match up" the map graphic to the underlying (or overlaying?) created grid? Obviously I want to use the nodes/hex edges to define the terrain using TMN for rules of movement, LOS etc..

    Because I am a poor beginning coder, will TMN integrate and work with a visual scripter such as Antares Universe or UScript. This is the way I am more likely to code things as Im more a graphics person so doing things like coding visually is easier for me to grasp instead of long pages of dry code blocks I cant follow :)

    Thanks for your time
     
    Last edited: Jul 17, 2013
  31. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    I'm not quite sure what you are saying/ asking. Perhaps you can explain better by attaching a screenshot of the problem?
    Map&Nav is just a grid and nodes system. The sample art are used with the samples scenes. I can't help with issues regarding your art work.
     
  32. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Yes, you can move nodes around to match with your layout if it is not a standard grid that the nodes could fit over. Check the videos linked in the first post to see how a grid is created with the provided tools.

    There is no Antares/ UScript support out of the box. I think some users created actions/blocks, or whatever the are called, and posted about it a few posts back. I am not sure how well those work with Antares/ UScript though.

    Note that Map&Nav is written in C# and you would have to be able to read the code comments to understand how to use it in something you want to create. So, some good programming experience required with using this package ;)
     
  33. Aladinho

    Aladinho

    Joined:
    Jul 18, 2013
    Posts:
    9
    Do you have any idea for fog of war ?
    Like the unit has 7 visible range so from the unit in every direction for 7 node will not see more that that.
     
  34. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    You could try the TileNode.GetAllInRange(....) function to find the "visible" tiles.
     
  35. csshelton70

    csshelton70

    Joined:
    Nov 26, 2012
    Posts:
    16
    Leslie,

    How difficult would it be ( and if not very difficult, just get me started in the correct direction ) to render a hex-grid directly on the surface of the terrain? Not the individual tile outlines like can be done now with showing the markers, but a very thin line that adheres to the terrain object that denotes the different hex tiles?
     
  36. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    I'm guessing you would need to use projector(s) to render it, which is a very expensive process as far as I know. There are probably better ways but I've never done research on this and only know of Unity's projectors to cast images that adheres to the shape below it.

    Whatever you use you would create this separate from the actual mapnav grid, so whatever you choose would not influence m&n. Think of it in terms of how the room and that one hex-tile scene works. The "outlines" are build into the art and mapnav is this invisible thing that its on it.
     
  37. Azmodii

    Azmodii

    Joined:
    May 7, 2013
    Posts:
    4
    Hi Leslie,

    Let me first say what a great product you have!

    I am extremely happy with my purchase.

    I'm having a few issues. The first is I cannot get the grid to show up in my scene, no matter what I do.

    I make the MapNav, set the size, set the tile layer to tile (replicated your example project layers) and also set the prefab for the tile to TIlehex (The one without projectors). The grid creates but the material is not visible at all. I can tell that it isnt rendering by checking the draw calls (Changing the grid to 80x80 makes the editor run like junk as the gizmos render, but ingame is perfectly smooth as the hexes are not rendering).

    Here is an overview of what I am attempting to do.

    I have several planes set up over the place. I want to dump 1 mapnav for each plane. I can easily get the autoheight feature to wrap the grid around the "Terrain", I can do this with one map nav or several.

    What doesn't work, as explained, is it doesnt render the materials on the tiles in game view, and when jumping back to the scene view, it doesnt render there either.

    I have managed to get the tiles to render in the scene view by creating the mapnav, aligning it, wrapping it to the terrain, and then recreating the tiles. This however, doesn't render in game, and once the play button has been clicked - they cease to render in the scene as well.

    I havent modified any scripts or assets either.

    Any ideas?


    Quick Edit.


    I have managed to get the material showing in the scene by clicking "Tile nodes marker visibility".

    The issues I have then is once play is clicked, it doesnt remember this. Clicking "Tile nodes marker visibility" again in game view renders the tiles appropriately.

    It also makes an amazing amount of draw calls (One per tile). I'm working on optimising this (As technically they are all the same object using the same material). This should make larger maps more than possible.
     
    Last edited: Jul 22, 2013
  38. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    They are not really tiles. The things that show up in-game are just markers that show up if you turn them on (off by default). For example, in the sample scenes they are used to indicate how far a unit can move when you select a unit.

    There are several ways to show them,
    MapNav.ShowTileNodeMarkers() to show all from a map
    TileNode.Show() to show a node
    TileNode.ShowNeighbours() to show neighbours around it in radius count of nodes and other variations on ShowNeighbours.

    Most will also turn on the collier associated with the node since it expects you are showing them to get input form the player (ray cast from mouse click for example) so just modify the functions if you need functionality that differ from how mapnav works.
     
  39. bakkoto

    bakkoto

    Joined:
    Aug 5, 2012
    Posts:
    24
    Hi Leslie,

    can you please help me fix these problems :

    1. Showing Marker-nodes in Tile-nodes that are out of map :

    $Markers outside the map.PNG

    2. Showing Marker-nodes in Tile-nodes that are already occupied ( for exemple : if an ally unit stand in my Attack-Range there is no need to show the Range-marker in the ally unit tile-node) :

    $Markers on occupied node.PNG

    maybe adding something like "TileNode.TileType validNodesLayer" as argument to the methode "RadiusMarker.show()" ??

    what would you suggest to solve these problems?

    Many thanks in advance for your help.
     
    Last edited: Aug 1, 2013
  40. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    RadiusMarker is just a little sample script I threw in and it is not really very robust. For one it shows its markers even if there is no nodes under it.

    One way that it can check if there are nodes under it is to tell MapNav to turn on all the colliders for all the nodes and then it can cast rays to check what is under each of its markers but this can slow your game down when those colliders are turned on and off. Basically the same thing would have to be done for detecting allies, you first need to know what node is under the marker and then you can check what unit sits on that node.

    Another method might be, if you know what the "centre" node is over which it sits, to then use MapNav to get a list of all the nodes in a certain radius and only turn those colliers on so that the radiusmarker can do the above tests. It will be too hard to deduct which mapnav node each of the markers are over in any other way.
     
  41. bakkoto

    bakkoto

    Joined:
    Aug 5, 2012
    Posts:
    24
    Hi Leslie,

    so i tried something to fix this problem and here's what i came up with :

    casting rays to check what is under each markers (if there is a TileNode Under)

    $Markers Raycast.PNG

    here is my RayCast Function :

    Code (csharp):
    1.   private void markersRayCastTest()
    2.     {
    3.         RaycastHit hit;
    4.         float rayCastDistance = 10; // change later to 0.1f
    5.  
    6.         foreach (Transform child in transform) // children of created gameObject "Marker" ==> "00" ,"01"..etc
    7.         {
    8.             foreach (Transform rangeNode in child) // TildeNodes  (all children of "00" and "01" etc.)
    9.             {
    10.                 Debug.DrawRay(rangeNode.position, -rangeNode.transform.up * rayCastDistance, Color.red);
    11.                 if (Physics.Raycast(rangeNode.transform.localPosition, -rangeNode.transform.up, out hit, rayCastDistance))
    12.                 {
    13.                     if (hit.transform.gameObject.layer == LayerTileNode)
    14.                     {
    15.                         Debug.Log("A tile node is detected");
    16.                     }
    17.                     else
    18.                     {
    19.                         Debug.Log("Nothing detected");
    20.                         rangeNode.gameObject.SetActive(false);
    21.                     }
    22.                 }
    23.             }
    24.         }
    25.     }
    defining the TileNode-Layer for the RayCast (inside "RadiusMarker" class) :

    Code (csharp):
    1. void Start()
    2.     {
    3.         HideAll();
    4.         LayerTileNode = LayerMask.NameToLayer("tile");
    5.     }
    Calling the the RayCast Function in RadiusMarker.Show() :

    Code (csharp):
    1. public void Show(Vector3 pos, int radius, bool adaptToTileHeight = false)
    2.     {
    3.         HideAll();
    4.  
    5.         // 0 or less means to show nothing, so return now
    6.         if (radius <= 0) return;
    7.  
    8.         // check if within limit
    9.         if (radius > markerNodes.Length) radius = markerNodes.Length;
    10.  
    11.         // now show nodes
    12.         for (int i = 0; i < radius; i++)
    13.         {
    14.             markerNodes[i].SetActive(true);
    15.         }
    16.         // move it to given position
    17.         transform.position = pos;
    18.  
    19.         //Raycast-Test to know which marker-node should be enabled/disabled.
    20.         this.markersRayCastTest();
    21.  
    22.         if (adaptToTileHeight || this.adaptToTileHeight) UpdateNodeHeight(radius, false);
    23.     }
    Normally it should work and these extra-Markers should be disabled ==>

    $Markers to disable.png

    One of the main problems that the Raycast "out hit" parameter didn't recognize the "LayerTileNode" so it jumps directley to the else statement (disabling all markers Node :( )
    notice : i´ve tested the raycast with the tileNodes using a simple "Cube gameobject as Ray-caster" and it´s work fine.

    I´m not sure what is causing these issues and if there´s a better way to write a code with a similar functionality (or something to fix this code) or if someone did find a better solution, please let me know .it will be appreciated.
    Many thanks in advance for your help.
     
    Last edited: Aug 5, 2013
  42. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    You will need the else{} for the "raycast if" so that you can disable the node if no hit was detected, else you end up with what you see in the last shot.

    If you wnat to feed the Raycast function a layer then first make it into a mask like so...
    LayerMask rayMask = (1 << LayerTileNode);
     
  43. bakkoto

    bakkoto

    Joined:
    Aug 5, 2012
    Posts:
    24
    Hi again

    I'm sorry but i'm a little bit confused due to the fact that I've never worked with raycasts before.

    Did you mean something like this :

    Code (csharp):
    1.  private void markersRayCastTest()
    2.     {
    3.         RaycastHit hit;
    4.         float rayCastDistance = 10; //change later to 0.1f
    5.         LayerMask rayMask = (1 << LayerTileNode);
    6.  
    7.         foreach (Transform child in transform)
    8.         {
    9.             foreach (Transform rangeNode in child)
    10.             {
    11.                 Debug.DrawRay(rangeNode.position, -rangeNode.transform.up * rayCastDistance, Color.red);
    12.                 if (Physics.Raycast(rangeNode.transform.localPosition, -rangeNode.transform.up, out hit, rayCastDistance, rayMask))
    13.                 {
    14.  
    15.                     Debug.Log(hit.transform.gameObject.layer); // Nothing is showing up in the console
    16.  
    17.                     if (hit.transform.gameObject.layer == LayerTileNode)
    18.                     {
    19.                         Debug.Log("A tile node is detected");
    20.                     }
    21.                     else
    22.                     {
    23.                         Debug.Log("Nothing detected");
    24.                         rangeNode.gameObject.SetActive(false);
    25.                     }
    26.                 }
    27.             }
    28.         }
    29.     }
    Still doesn't work :(

    Also, i m getting no response from the "Debug.Log(hit.transform.gameObject.layer)" in the Debugging Console. Normally it should be 20 for "tile" layer.

    Notice :

    the yellow Ground GameObject Layer is set to "Ignore Raycast"

    $ground layer.png
     
  44. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Try this. If I understood your the previous post correctly then you show All nodes and then make a call to markersRayCastTest(), which should turn off those that should not be visible. So the below code will check for a ray hist against something in the mask and if not then hide the node.

    Code (csharp):
    1.  
    2. private void markersRayCastTest()
    3. {
    4.     RaycastHit hit;
    5.     float rayCastDistance = 10; //change later to 0.1f
    6.     LayerMask rayMask = (1 << LayerTileNode);
    7.     foreach (Transform child in transform)
    8.     {
    9.         foreach (Transform rangeNode in child)
    10.         {
    11.             if (false == Physics.Raycast(rangeNode.transform.localPosition, -rangeNode.transform.up, out hit, rayCastDistance, rayMask))
    12.             {
    13.                 rangeNode.gameObject.SetActive(false);
    14.             }
    15.         }
    16.     }
    17. }
     
  45. bakkoto

    bakkoto

    Joined:
    Aug 5, 2012
    Posts:
    24
    That´s right. That's exactly what i'm trying to achieve.
    I tested your Code but sadly doesn't work :( . All Range-Markers are disabled no matter where the player stand.So the raycast return always "false" :-?.Like i said before the Raycast "out hit" parameter can´t recognize the "LayerTileNode" for some unknown reason.
     
  46. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Is this correct, Tile spelled in all lower caps is correct?
    LayerTileNode = LayerMask.NameToLayer("tile");

    LayerTileNode is of type "int"?

    Did you check if the colliders are on for the Tile Nodes? Pause the game and click on of the "visible" ones to make sure if the collider is actually on.
     
  47. bakkoto

    bakkoto

    Joined:
    Aug 5, 2012
    Posts:
    24
    yes it´s correct. I´ve tested the raycast with the tileNodes using a simple "Cube gameobject as Ray-caster" and it´s work fine (same Syntax ,same variables ,same Names)

    $Cube Ray cast.PNG

    Raycast test code :

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class RayCastTest : MonoBehaviour
    5. {
    6.     private int Layer1;
    7.     private int Layer2;
    8.     public Transform rayCasterObject;
    9.     public float rayCastDistance = 10;
    10.     public string LayerNameToTest = "tile";
    11.  
    12.     void Start()
    13.     {
    14.         Layer1 = LayerMask.NameToLayer(LayerNameToTest);
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         rayCastMethode_2();
    20.     }
    21.  
    22.     //private void rayCastMethode_1()
    23.     //{
    24.     //    if (Input.GetMouseButtonDown(2))
    25.     //    {
    26.  
    27.     //        Ray ray = Camera.mainCamera.ScreenPointToRay(Input.mousePosition);
    28.     //        RaycastHit hit;
    29.  
    30.     //        // Raycast
    31.     //        if (Physics.Raycast(ray, out hit, 500f))
    32.     //        {
    33.     //            if (hit.transform.gameObject.layer == Layer1)
    34.     //            {
    35.     //                Debug.Log("A tile node is detected");
    36.     //            }
    37.     //            else
    38.     //            {
    39.     //                Debug.Log("Nothing detected");
    40.     //            }
    41.     //        }
    42.     //    }
    43.     //}
    44.  
    45.     private void rayCastMethode_2()
    46.     {
    47.         RaycastHit hit;
    48.  
    49.         Debug.DrawRay(rayCasterObject.position, -rayCasterObject.transform.up * rayCastDistance, Color.red);
    50.  
    51.         if (Physics.Raycast(rayCasterObject.position, -rayCasterObject.transform.up, out hit, rayCastDistance))
    52.         {
    53.             if (hit.transform.gameObject.layer == Layer1)
    54.             {
    55.                 Debug.Log("object down detected");
    56.             }
    57.             else
    58.             {
    59.                 Debug.Log("Nothing down detected");
    60.             }
    61.         }
    62.        
    63.     }
    64.  
    65. }
    66.  
    yes they are on for Tile Nodes and also for Markers Nodes.
     
  48. blaze

    blaze

    Joined:
    Dec 21, 2011
    Posts:
    211
    This script works with 400x400(tiles) maps?
    The Navigation works well with 200+ units?
    The source code is included?
     
  49. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Map&Nav is best for 80x80 or smaller maps.
    I have no idea how 200 units will perform on turn based movement but I'm sure 200 units trying to move at the same time will perform very poorly.
    Source is included (C#)
     
  50. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    The Marker Nodes, that is the ones on the Radius Marker? They are not on layer "tile" too are they?

    I the code you posted an example of something that is working? If so, then a modification to that to turn off a node when nothing is hit would be all you need.

    Code (csharp):
    1.  
    2. if (Physics.Raycast(rayCasterObject.position, -rayCasterObject.transform.up, out hit, rayCastDistance))
    3. {
    4.     if (hit.transform.gameObject.layer == Layer1)
    5.     {
    6.         Debug.Log("object down detected");
    7.     }
    8.     else
    9.     {
    10.         Debug.Log("Nothing down detected");
    11.     }
    12. }
    13. else
    14. {
    15.     // hide marker here since there was nothing underneath
    16. }
    17.