Search Unity

Tile Based Map Nav

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

  1. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Or adding Normal to it if it's a lake that's frozen but not all of the time.
     
  2. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    to add you simply do this...
    node.tileTypeMask = (TileNode.TileType.Normal | TileNode.TileType.Air);

    to remove you should be able to use something like this...
    node.tileTypeMask = (node.tileTypeMask ~TileNode.TileType.Air);

    or simply do this if you know you only want normal/land and nothing else on it...
    node.tileTypeMask = TileNode.TileType.Normal;
     
  3. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    I have been trying to set up some custom actions for this in Playmaker. So far i have been able to create a working spawnunit, selection indicator and radius marker action. I am struggling to get an action that moves a unit working though. I am still fairly new to c# so its probably something obvious i am doing wrong.

    For example the working SpawnUnit action looks like this:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using HutongGames.PlayMaker;
    4.  
    5. namespace HutongGames.PlayMaker.Actions
    6. {
    7.     [ActionCategory("Custom")]
    8.     [Tooltip("Spawns a mapnav unit")]
    9.    
    10.     public class MapNavUnitSpawn : FsmStateAction
    11.     {                      
    12.         public FsmGameObject chooseUnitFab;
    13.         [UIHint(UIHint.Variable)]
    14.         public FsmGameObject storeUnitFab;         
    15.        
    16.         public MapNav map;
    17.        
    18.         public FsmGameObject nodeSelect;
    19.         [UIHint(UIHint.Variable)]
    20.         public FsmGameObject storeUnitNode;
    21.        
    22.         private TileNode node;
    23.        
    24.         private GameObject unitFab;
    25.        
    26.         public override void OnEnter ()
    27.         {
    28.             unitFab = chooseUnitFab.Value;
    29.             storeUnitFab.Value = unitFab;
    30.  
    31.             node = nodeSelect.Value.GetComponent<TileNode>();
    32.             storeUnitNode = nodeSelect.Value;
    33.                
    34.            
    35.             if (node.units.Count == 0)
    36.             {
    37.             Unit.SpawnUnit(unitFab, map, node);
    38.            
    39.            
    40.             }
    41.            
    42.             Finish ();
    43.         }              
    44.     }
    45. }
    46.  
    47.  
    48.  
    All the variables beginning with Fsm are just to give better functionality within playmaker. You can just make the node and unitPrefab public and drag from the hierarchy to set them and it works.

    For movement i am just trying to call the MoveTo function:

    Code (csharp):
    1.  
    2. public class MapNavUnitMove : FsmStateAction
    3.     {
    4.        
    5.         public FsmGameObject moveToNode;
    6.         public FsmGameObject unitToMove;
    7.  
    8.        
    9.         private TileNode targetNode;
    10.         private Unit selectedUnit;
    11.        
    12.    
    13.         public override void OnEnter ()
    14.        
    15.         {
    16.             targetNode = moveToNode.Value.GetComponent<TileNode>();
    17.             selectedUnit = unitToMove.Value.GetComponent<Unit>();
    18.    
    19.              selectedUnit.MoveTo(targetNode);
    20.  
    21.             Finish();
    22.         }
    23.     }
    24.  
    But i get NullReferenceException: Object reference not set to an instance of an object
    NaviUnit.MoveTo (.TileNode targetNode) (at Assets/Tile Based Map and Nav/Scripts/TMN/NaviUnit.cs:211)

    What am i missing?
     
  4. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Since the error is happening at NaviUnit.cs:211, it means this line ...
    followPath = mapnav.GetPath(this.node, targetNode, this.tileLevel);
    which could indicate that the variable "mapnav" is not set.

    Check that you are passing correct values to the Spawn call at Unit.SpawnUnit(unitFab, map, node);
    map and node should not be null.
     
  5. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    is the variable mapnav something i need to set in addition to "public MapNav map"?

    To make it simpler for me, i created an empty scene, generated a small mapnav, then made a simple gamecontroller script (attached to an empty gameobject) that i want to spawn a unit and move it to a different node:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MyGameController : MonoBehaviour {
    6.    
    7.     public MapNav map; 
    8.     public TileNode node;  
    9.     public GameObject unitFab; 
    10.     public TileNode targetNode;    
    11.     public Unit selectedUnit;
    12.        
    13.     void Start () {
    14.                        
    15.             Unit.SpawnUnit(unitFab, map, node);
    16.             selectedUnit = unitFab.GetComponent<Unit>();       
    17.             selectedUnit.MoveTo(targetNode);   
    18.     }  
    19. }
    20.  
    In the inspector, i drag the mapnav from the hierarchy into the map variable, the p1_unit_land prefab into unitFab, the node i want it to spawn on into node, and the node i want it to move to into targetNode.

    Clicking play, the unit appears on whatever Tilenode i have dragged into node, but then the exact same error as above appears and no movement happens.
     
  6. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    You are trying to move a prefab, not a unit in the scene.
    Try this...
    Code (csharp):
    1.  
    2. void Start () {
    3.             selectedUnit = Unit.SpawnUnit(unitFab, map, node);
    4.             selectedUnit.MoveTo(targetNode);  
    5.     }  
    6.  
     
  7. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    Got me a bit further, i can see in the inspector when i hit play that selected unit is now correctly set as a unit in the scene, but now the error it throws is:

    NullReferenceException: Object reference not set to an instance of an object
    MapNav.GetPath (.TileNode fromNode, .TileNode toNode, TileType validNodesLayer) (at Assets/Tile Based Map and Nav/Scripts/TMN/MapNav.cs:117)
     
  8. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Please make sure you are not passing/makings calls on a prefab again and that the mapnav object you are calling is an actual game object in the scene.
    The only thing that can be null on line 117 of MapNav is the nodes variable and that should have been inited in the Start() call of MapNav.
     
  9. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    I had been playing with that project for a while, and it occurred to me that a stray child/cat/wife may have pushed buttons on the pc whilst the editor window was open and i wasnt around. Just in case i decided to start completely fresh. New project, imported tile map and nav from the asset store. Spawned a new MapNav, hex, 5 x 5. Followed the same steps as above creating the gamecontroller script, setting the variables etc.

    I had to cast the selectedunit as a unit:

    Code (csharp):
    1.  
    2. public class MyGameController : MonoBehaviour {
    3.    
    4.     public MapNav map; 
    5.     public TileNode node;  
    6.     public GameObject unitFab; 
    7.     public TileNode targetNode;    
    8.     public Unit selectedUnit;
    9.  
    10.        
    11.     void Start () {
    12.                        
    13.             selectedUnit = Unit.SpawnUnit(unitFab, map, node) as Unit; 
    14.             selectedUnit.MoveTo(targetNode);   
    15.     }  
    16. }
    17.  
    I attached a screenshot of the inspector and hierarchy. $Screen shot 2012-07-23 at 9.13.12 PM.png

    The nodes and MapNav are dragged straight from the hierarchy into their respective fields.

    Now when i hit play, the error is:

    NullReferenceException: Object reference not set to an instance of an object
    NaviUnit.LinkWith (.TileNode targetNode) (at Assets/Tile Based Map and Nav/Scripts/TMN/NaviUnit.cs:116)

    And i also noticed that the Selected Unit field doesnt populate in the inspector after hitting play.

    Sorry for the confusion, and thankyou for your help so far!
     
  10. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Script execusion order might be messing with you here.
    You should not really move a Unit in the Start() seeing as MapNav uses Start to init and might not have had its Start called before this controller's start.
    Try this,

    Code (csharp):
    1.  
    2. IEnumerator Start()
    3. {
    4.     yield return null; // wait for a frame,
    5.     selectedUnit = Unit.SpawnUnit(unitFab, map, node) as Unit;
    6.     selectedUnit.MoveTo(targetNode);       
    7. }
    8.  
     
  11. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    Sweet success, never been so happy to see a little tank move across the screen!

    Thanks again!
     
  12. deathripper

    deathripper

    Joined:
    Jul 18, 2012
    Posts:
    4
    Hi I want to create a Bomberman like game and just discovered Tile based Map Nav.

    I was wondering if the controls only support mouse controls or if I could also use WASD movement ?
     
  13. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    The provided examples shows how to use mouse input, but you could easily add WASD or even touch input since the core of Map&Nav is not bound to any input system.
     
  14. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    Funnily enough this is exactly what i have been looking at too. This is how I thought about going about it, this is for a square grid with no diagonal movement:

    Code (csharp):
    1.  
    2. public int mapLength = 12 //ie for a 12x12 map
    3. private Unit playerUnit;
    4. private TileNode playerCurrentNode;
    5. private TileNode moveToNode;
    6.  
    7.  
    8. public void GetNodeUp(TileNode playerCurrentNode)
    9.        
    10.     {
    11.         int r = playerCurrentNode.idx;
    12.         moveToNode = map[(r + mapLength)];
    13.     }
    14.    
    15.     public void GetNodeDown(TileNode playerCurrentNode)
    16.        
    17.     {
    18.         int r = playerCurrentNode.idx;
    19.         moveToNode = map[(r - mapLength)];
    20.     }
    21.    
    22.     public void GetNodeLeft(TileNode playerCurrentNode)
    23.        
    24.     {
    25.         int r = playerCurrentNode.idx;
    26.         moveToNode = map[(r - 1)];
    27.     }
    28.    
    29.     public void GetNodeRight(TileNode playerCurrentNode)
    30.        
    31.     {
    32.         int r = playerCurrentNode.idx;
    33.         moveToNode = map[(r + 1)];
    34.     }
    35.  
    36. void Update () {
    37.    
    38.          if (Input.GetButtonUp ("w"))
    39.         {
    40.         GetNodeUp(playerCurrentNode);
    41.         playerUnit.MoveTo(moveToNode);     
    42.         }
    43. //etcetc for all directions
    44.  
    Would that work in theory?

    In my noobness i cant figure out how to assign playerUnit when it spawns. I am just wanting a single unit, spawned at the start, that the player controls. So i have done like we discussed above:

    Code (csharp):
    1.  
    2. IEnumerator Start () {
    3.     yield return null;
    4.     playerUnit = Unit.SpawnUnit(playerUnitFab, map, playerSpawnNode) as Unit;
    5.     }
    6.  
    But when i press the w key trying to move up, i get a NullReferenceException: Object reference not set to an instance of an object. On the playerUnit.MoveTo(moveToNode); line.
     
  15. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    Ugh, noob moment overcome, i had changed the name of my unit script to player, thats what messed it up. Working now!
     
  16. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    @Arghonaut
    You can use MapNav.nodesXCount. It should be the same as your mapLength variable.
    moveToNode = map[(r + map.nodesXCount)];
     
  17. soulis6

    soulis6

    Joined:
    Apr 21, 2011
    Posts:
    22
    Purchased this a few weeks ago, and it's been a big help so far, but I did have a quick question:

    Are there any functions other than ShowNeighbours that calculate a path including walls and other units? Basically Tilenode.IsInRange is what i'm looking for, but also taking into account for blocked tiles. Does something like that exist currently?
     
  18. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    no, but I'll add some functions (or function) related to that with options so you can choose what to include in the returned array of nodes. Will update tonight.

    [edit] The fucntion is TileNode.GetAllInRange(...)
     
    Last edited: Jul 31, 2012
  19. TomS

    TomS

    Joined:
    Feb 16, 2012
    Posts:
    2
    I bought this package tonight and when I was trying to create a navmap using the window New MapNav, the editor is throwing this error(dumped from the Editor Log),
    Code (csharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2.   at MapNav.CreateTileNodes (UnityEngine.GameObject nodeFab, .MapNav map, TilesLayout layout, Single tileSpacing, Single tileSize, TileType initialMask, Int32 xCount, Int32 yCount) [0x001e5] in C:\Users\Tom\Dropbox\Hex Strategy Game\Assets\Tile Based Map and Nav\Scripts\TMN\MapNav.cs:289
    3.  
    4.   at MapNavEditor.OnInspectorGUI () [0x0040d] in C:\Users\Tom\Dropbox\Hex Strategy Game\Assets\Tile Based Map and Nav\Editor\MapNavEditor.cs:138
    5.  
    6.   at UnityEditor.InspectorWindow.DrawEditors (Boolean isRepaintEvent, UnityEditor.Editor[] editors, Boolean eyeDropperDirty) [0x004ad] in C:\BuildAgent\work\d9c061b1c154f5ae\Editor\Mono\Inspector\InspectorWindow.cs:888
    7.  
    8.   at UnityEditor.InspectorWindow.OnGUI () [0x0007b] in C:\BuildAgent\work\d9c061b1c154f5ae\Editor\Mono\Inspector\InspectorWindow.cs:243
    9.  
    10.   at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (object,object[],System.Exception)
    11.  
    12.   at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
    13.  
    14. (Filename: Assets/Tile Based Map and Nav/Scripts/TMN/MapNav.cs Line: 289)
    15. *Formatted as code for legibility
    This is an issue I can't fix due to it being an issue in the code itself, as I have not modified any of it and only dealt with it through the editor tools provided. I am sure you will offer a speedy fix, thank you.
     
  20. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    It looks like you specified something in the "TileNode Prefab" option of the create window, but that something was not actually a TileNode prefab. The included sample TileNode Prefabs are located in \Assets\Tile Based Map and Nav\Prefabs\tile_nodes. Anything else is not a TileNdoe prefab since they do not have the correct component (script) attached. If you are trying to make your own TileNdoe Prefab, then make sure it has the TileNode component attached.
     
  21. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    853
    Looking at Arghonaut's post above, what's the easiest way to find out whether or not a tile is occupied or not? Neither the NavMap nor the unit itself seem to store their current position in an obvious variable, so I guess things happen under the hood somewhere...?

    [edit] GetUnitInLevel I suppose?
     
    Last edited: Jul 31, 2012
  22. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    TileNode.units is a list of all units on the node. So if (node.units.Count > 0) then there is a unit on the node. Each unit knows where it is standing via NaviUnit.node.

    Of course all these will be broken if you move the unit around yourself or don't use the provided spawning function and don't link up to the node it is spawned over or moved to. The NaviUnit functions to move and spawn units do this.
     
  23. Spacecon

    Spacecon

    Joined:
    Jul 22, 2012
    Posts:
    1
    It was asked a bit ago, but have you given any thought to units larger than a single node?
     
  24. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    I have no plans at the moment to implement such a feature since the system was not really designed for that in mind, so it would take a while to rewrite a few things and I am currently bussy with a new project. I can only give support and updates/fixes for the current features of Map&Nav, but not add big new features.
     
  25. CrucibleLab

    CrucibleLab

    Joined:
    May 29, 2012
    Posts:
    19
    Hey guys,

    I bought this asset and have been fiddling with it for a few days. One of the things I am trying to accomplish but wasn't able to figure out is how to actually destroy a unit when a projectile (e.g., missile) is fired at it? Please correct me if I am wrong but looking at the code, it looks like the 'Attack' method is targeting the node instead of the unit that is sitting on the node.

    Would you (looking at Leslie) give me a tip on how to actually reference any given unit or some sample code? Didn't mean to sound like a bum but I am fairly new to C# and Unity 3D.

    Thanks!
     
  26. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    ugh.. I typed this whole reply and when I hit send my inet died and then the back button would not show this form again. Let me try again :(

    The provided attack sample is very simple and just there to get you started. Looking SampleWeapon.cs you will notice there is a "Play(Unit target)" function which is caleld when an attack is amde on the target unit and the effects should start playing. Sabe this unit to some temp variable which yo ucan recall once the weapon is done with its effect, in this case a missile flying over to the target.

    Now that you have the target unit saved off you can recall it when OnFXMissileReachedTarget(..) is called. Tis fuction is called when the weapon's effects are done (the missile reached the destination). In this function I would make a call to the targeted unit to tell it to take x-amount of damage, check if the HP is uner zero, and if so, start a ncie explosion effect and destroy the unit game object.

    Bes ure to update the TileNode's units llist when you destroy a unit. Each tilenode keeps record of what unit(s) are standing on it and each unit knows on which node it is standing. So a call like target_unit.node.units.Remove(target_unit); should do the trick to remove the unit from the node it is standing on and then you can destroy the unit's gameobject.
     
  27. CrucibleLab

    CrucibleLab

    Joined:
    May 29, 2012
    Posts:
    19
    Aww... that must've been painful. Thanks for taking time to respond!

    Now, in the SampleWeapon.cs file, I simply tried adding the following code to test getting rid of the target unit:
    Code (csharp):
    1. GameObject.Destroy(target, 0.1f);
    When I run the game and fire a missile at the target unit, the unit remains visible. But when I fire another missile at the same target, I get an error that says, "NullReferenceException: Object reference not set to an instance of an object".

    It seems to tell me that the target unit has been actually destroyed, programmatically speaking. But the object remains only visibly. I also tried adding the following code (as you advised), hoping to see the unit disappear after the missile hit:
    Code (csharp):
    1. target.node.units.Remove(target);
    But, the target unit is still there. Hmm... :confused: Don't mean to bug you too much but any further insight will be very helpful. Thanks again!
     
  28. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    I am trying to use a radius marker to target an attack that does damage over an area, is there a way to have the centre tile of the marker shown? I am using a raycast to select the node that will be targeted, then displaying a radius marker around this node. I tried just using targetNode.Show(); but this uses a different marker prefab than the attack range marker.

    Code (csharp):
    1.  
    2.             if (Physics.Raycast(ray, out hit, 500f, _rayMask))
    3.             {
    4.                 if (hit.collider.gameObject.layer == map.tilesLayer)
    5.                 {
    6.                     if(targetNode != null) targetNode.Hide();
    7.                    
    8.                     targetNode = hit.collider.gameObject.GetComponent<TileNode>();
    9.                     attackDistance = selectedUnit.node.TileCountTo(targetNode);
    10.                        
    11.                         if (attackDistance <= selectedUnit.attackRange)
    12.                     {
    13.                              // targetNode.Show();     
    14.                         radius4.Show(targetNode.transform.position, selectedUnit.attackRadius - 1); //need marker to also show on clicked node.
    15.                     }                  
    16.                 }                  
    17.             }
    18.  
     
  29. Raspilicious

    Raspilicious

    Joined:
    Jun 21, 2012
    Posts:
    24
    I've just overcome this in my own project, this is what I have done. It's in the 'Unit' script which is of course attached to each unit.
    Code (csharp):
    1. private void OnAttackDone(NaviUnit unit, int eventCode)
    2.     {
    3.         targetUnit.currHealth = (targetUnit.currHealth - this.attackDamage);
    4.         if (targetUnit.currHealth <= 0) {
    5.             targetUnit.LinkWith(null);
    6.             Destroy(targetUnit.gameObject);
    7.         }
    8.         // tell whomever is listening that I am done with my attack. eventCode 2
    9.         if (onUnitEvent != null) onUnitEvent(this, 2);
    10.     }
    I have variables for how much current health a unit has, along with how much attack damage they can deal.

    This script basically runs through from start to finish as such:
    - Deals damage to the target unit according to how much attack power the attacker has
    - If the target unit has less than 0 health left (or equal to, which effectively is the same thing) then it unlinks the target unit from it's node and destroys the game object of the target unit
    - Runs Leslie's code 'OnUnitEvent' to perform other actions after the unit has been damaged/killed

    When the eventcode returns 2, I display the movement and attack ranges again (in the other script GameController), as my units can perform multiple actions per turn, but that's up to your own discretion of course.
     
  30. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    @CrucibleLab, You are only destroying the Component when you call GameObject.Destroy(target, 0.1f); Remember, target there is of type Unit, a component of the Unit GameObject. You need to call GameObject.Destroy(target.gameObject, 0.1f);

    [edit]
    Raspilicious' solution looks pretty good, nice use of LinkWith() :)
    @CrucibleLab, targetUnit is a variable that can be stored as a privare var of the Unit class and can be set in the Attack() fcuntion, like around line 120 of Unit.cs you could add this.targetUnit = target;
     
    Last edited: Aug 7, 2012
  31. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    The RadiousMarker do not have a center node since it was assumed it would be used over a selected unit. You can hack it by adding a node.After you created a radius marker you will notice it has no center node, so expand it in the hierarchy and then expand 00, (Marker -> 00). Duplicate one of the objects in there and position that new objected to the center. Now when you ask for a radius of 1 or more to be shown it will also show the center object (marker) since it is part of radius 1.
     
  32. CrucibleLab

    CrucibleLab

    Joined:
    May 29, 2012
    Posts:
    19
    @Leslie Raspilicious,

    You guys made my day! Not only was I able to get it working but also I am improving my grasp of the back-end coding. I got many more hurdles to jump through but this is definitely an exciting start. :)

    Thanks, again!
     
  33. CrucibleLab

    CrucibleLab

    Joined:
    May 29, 2012
    Posts:
    19
    Leslie (or fellow users),

    I want to spawn a unit at a specific node on the map as opposed to on a random one. I noticed in the code that units are being placed on randomly selected nodes as following code snippet shows:
    Code (csharp):
    1. r = Random.Range(0, map.Length);
    2. if (unitFab.CanStandOn(map[r].true)) {
    3.      node = map[r];
    4. }
    5. ...
    6. Unit unit = (Unit) Unit.SpawnUnit(unitFab.gameObject, map, node);
    So, I understand the logic behind how units are randomly spawning on the map but I have no clue as to how to select a specific node. Any help will be much appreciated!
     
  34. Arghonaut

    Arghonaut

    Joined:
    Jul 23, 2012
    Posts:
    26
    Plenty of ways. Quickest is just to declare a public TileNode variable and drag the node you want (All the nodes are children of the MapNav gameObject, node00, node01 etc etc) from the hierarchy into the inspector:
    Code (csharp):
    1.  
    2. public TileNode spawnNode;
    3.  
    then use that node in the spawnunit method.

    If you look at the sample06 scene that comes with the package you will see a way to use raycasting to select the node, in one of my code snippets above i also do similar.

    Otherwise, in the code you have above, instead of using the the random int in r, just manually type the node number you want, ie:

    Code (csharp):
    1.  
    2. node = map[10];
    3.  
     
  35. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    +1 to Arghonaut's answer.

    Selecting the node to use is up to your design. Do you have a specific position in mind at design/edit time, then create public variable(s) somewhere like in the main controller so that you can drag the nodes into it. The "MapNav" game object contains all the nodes, these are what you want.

    If you want the player to click where topspawn, then look at sample scene 6.

    Do you want to spawn units around some base unit, then query that unit for its node and then ask that node for its neighbours, TileNode.nodeLinks. (some_construction_unit.node.nodeLinks). "nodeLinks" is an array of nodes around the specified node. Make sure to test for "null" since nodes on the border will have "null" neighbours and you might also wanna check if something is not alrleady standing on that spot (TileNode.units).

    Placing units at design time (in the ediytor) is not really an option cause there are too many things that needs to be called at runetime to get the unit going, like linking it with the node after nodes where inited and calling the unit's init function to connect the callbacks, if you are using these, etc. Basically you want to build on Arghonaut's first suggestion about creating a spawn variable but you might also want to have another variable to tell which unit prefab to use. This could be as simple as two arrays, one for the nodes to spawn on and one for what unit prefab to sapwn and then you simply run through these arrays in a Start() function to spawn the units. Here's some code...

    First define something that can hold the needed info
    Code (csharp):
    1.  
    2. [System.Serializable]
    3. public class SpawnInfo
    4. {
    5.    public GameObject targetNode; // node to spawn over
    6.    public GameObject unitFab; // unit to spawn
    7. }
    8.  
    Now modify you main game controller, first add a new variable that you can access in the inspector...
    Code (csharp):
    1.  
    2. public SpawnInfo[] spawn;
    3.  
    btw, this is GameController.cs but I hope people are only using it to learn from and then create their own controllers since the ones I provide in the samples has way too much things going on that you might not need in your own game, but lets assume you are modifying GameController.cs ...

    arround line 118 (inside the Update() fcuntion you will see SpawnRandomUnits(spawnCount); being called, repalce it with SpawnMyUnits(); and then add the following function ...

    Code (csharp):
    1.  
    2.     private void SpawnMyUnits()
    3.     {
    4.         for (int i = 0; i < spawn.Length; i++)
    5.         {
    6.             TileNode node = spawn[i].targetNode.GetComponent<TileNode>();
    7.             Unit unit = (Unit)Unit.SpawnUnit(spawn[i].unitFab, map, node);
    8.             unit.Init(OnUnitEvent);
    9.             unit.name = "unit-" + i;
    10.             units[unit.playerSide - 1].Add(unit);
    11.         }
    12.     }
    13.  
    note, I did not test any of this code.
     
  36. Wudek

    Wudek

    Joined:
    Aug 10, 2012
    Posts:
    7
    Hey, didn't see this anywhere, but I was thinking of using this in my game and I had a quick question.

    Basically, game involves being in third person view and moving around and I wanted to use the tiling script just for placing objects and to simplify what's where and positioning.

    However, I still want the physics of the terrain to work properly and I need the terrain to still have a smooth slope. Do tiles have to have the same height in it's whole area or can the tile be sloping and if I put an item on the tile, it will be rotated appropriately?
     
  37. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    The tiles can be anything you like. The navigation part of Map&Nav just won't be so usefull since it does not work with physics, but tile positions.

    Btw, if you did not yet purchase this, hold off for the asset I will be releasing in the week. It might be more suited to what you want ;)
     
  38. CrucibleLab

    CrucibleLab

    Joined:
    May 29, 2012
    Posts:
    19
    Folks,

    Here's something I've been trying to figure out for a few days to no avail. :(

    Using the 'Unit' script included in this asset, I added a simple condition to see if (for example) an enemy tank is in the sight of my tank and if so, I can fire a projectile to attack the enemy unit. For testing, what I did is I placed a few obstacles (simple cube objects each of which takes up a tile) between the two opposing units. In the 'Attack' function found in the 'Unit' script, I added the following:

    Code (csharp):
    1.  
    2. if (Physics.Linecase(transform.position, target.transform.position)) {
    3.      // The line of sight is clear, so can attack!
    4. } else {
    5.      return false;
    6. }
    7.  
    By the way, the above code is placed just above the following code:

    Code (csharp):
    1.  
    2. if (!CanAttack(target)) return false;
    3.  
    So, in theory, even if the two tanks are facing each other with an obstacle between them and they are within the firing range, I shouldn't be able to attack the enemy tank and vice versa. But, that is not the case. :confused: This behavior appeared at first to be rather straightforward to implement but now I feel as though I am missing (or misunderstanding) something in the context of this particular asset.

    Some tips/help will be much appreciated!
     
  39. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    I'd suggest you move the Linecast check into the "CanAttack" function so that you have that check everywhere a check neds to be done. Why it does not wok I don't know. Don;t know how deeply you debugged this but I would normally strat by adding some debug.logs in the 'if' and 'else' and after as a quick way to see exacty what gets executed.

    Here's a bit from Battlemass' CanAttack function to check if there are walls in the way (the only obstacle I checked for since units can attack through each other). Hit position in the code below is just a property of a unit that takes the unit's position and add some offset if needed. For example my flying units would have a certain offset from their real position which is on the tile/ground level while the unit's art is some dsiatnce above this position (I wanna be shooting at the art/body part, not the empty space below it)..

    Code (csharp):
    1.  
    2. Vector3 direction = target.HitPosition - this.HitPosition;
    3. float distance = direction.magnitude + 0.5f; // add a little more distance
    4. RaycastHit hit;
    5. int mask = ~(1 << 20);  // everything except unit layer (units are on layer 20)
    6. if (Physics.Raycast(this.HitPosition, direction, out hit, distance, mask))
    7. {
    8.     return false;
    9. }
    10.  
     
    Last edited: Aug 27, 2012
  40. Freezy

    Freezy

    Joined:
    Jul 15, 2012
    Posts:
    234
    I'm planning on purchasing this asset, is it compatible with the Unity 4.0 beta? (and will there be support for the official 4.0 release?)
     
  41. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Just tested and it works fine in Unity 4 beta; and yes, I'll fix any issues that might come up with Unity 4.
     
  42. LDM

    LDM

    Joined:
    Sep 11, 2012
    Posts:
    1
    Just bought this package and am super excited to be able to rapidly prototype a game using it!
     
  43. DanielFF

    DanielFF

    Joined:
    Aug 29, 2012
    Posts:
    41
    Hi,
    I bought the package, and I can not create a map. the setup window does not appear the field "Units Layer" as in the video. And when I click create, the nodes are not created.

    I'm using 3.5.5 Unit

    Any idea?

    Thank you.
     
  44. DanielFF

    DanielFF

    Joined:
    Aug 29, 2012
    Posts:
    41
    My bad,

    Forgot to set prefab....Im so noob :)

    Sorry and thank you!
     
  45. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
  46. Baykush

    Baykush

    Joined:
    Oct 10, 2012
    Posts:
    8
    Greetings!
    I'm currently planning a tile-based tower defense in which the terrain will constantly change. So i've got two questions:

    1 - Does the package supports real-time map modification, by that i mean - can i change the tile position in real time?

    2 - Is there any build-in pathfinding system in this package?

    thanks!
     
  47. Raspilicious

    Raspilicious

    Joined:
    Jun 21, 2012
    Posts:
    24

    1: I'm not sure myself, as I haven't tried to do it as yet, sorry.

    2: Yes there is built in pathfinding, using A* algorithms if I'm not mistaken, and is tile-based (tile, node, waypoint, all the same).
     
  48. Baykush

    Baykush

    Joined:
    Oct 10, 2012
    Posts:
    8

    Well, the path finding itself might turn the package worthy enought, altough i would like to know if anyone ever tried to move the tiles in real time.
     
  49. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    I am using an A* implementation which can calculate the path form one tilenode to another and return an array of the nodes which forms the path.

    About #1, each node is linked to its neighbouring nodes. So if you move it then things will get messy with the path finding depending on what you mean by moving the nodes. Maybe describe this a bit better sand I might come up with a better answer ;)
     
  50. Baykush

    Baykush

    Joined:
    Oct 10, 2012
    Posts:
    8
    You said all i need to know already, if the nodemesh is neighbour-dependant moving them would probably screw everything up, BUT i saw your videos and the tile blocking / jumping thing would pretty much solve my problem!

    Im honestly one click away of buying it, but a last question: does it work well for non turn-based games like TD and RTS? Does anyone or the developer tried to use the sistem for that kind of game before?

    Sorry for the questionspam, but my budget is tight and i need to make sure it's the right purchase! ^^'