[v1.4] Node Map - Node-based maps made easy

Node Map is a solution to create node-based maps in Unity. Node-based maps use a defined set of points (nodes) that the player or other units can move to using connecting routes between them (paths). Games may use node maps in a level select screen (such as Super Mario World), or as a way of showing travel (as in FTL).

I started this project because I wanted a node-based movement map for a game I’m working on. Not finding any acceptable solutions, I decided to roll my own. It didn’t take long before I realized this would be a tool others may find just as handy, so I started planning on how to make it as customizable and useful as possible for a variety of situations.

What I’m looking for here is input from the community to get an idea on what the must-have features are. I plan on having a fully-exposed API with events for detecting when various actions occur (arrived at Node, passed Marker, etc), path-finding that factors in distance as well as passable state for nodes or paths, and potentially integration into something like PlayMaker. I’m working on a number of included visual styles with the ability to incorporate your own models and sprites as well.


Maps can be rendered using 3D…

… or 2D!


Creating node maps couldn’t be easier!


2D or 3D? With Node Map… why not both?!

Features:

  • Quickly lay out and edit node-based maps in the Editor
  • Auto-positioning of path markers
  • Highly customizable visuals for nodes and paths
  • Renders both 2D and 3D maps: Change on the fly!
  • Multiple input types supported
  • Agent-based movement system with pathfinding
  • Fully-exposed API with events

is it possible to add a node between 2 nodes that are already created? / or those small nodes can act like those big nodes?

I like this.

not sure how agent-based movement would be implemented, but maybe some like me would make their own movement (and logic) and only need the position/transform of the next node (when path is calculated)

Thank you! Awaiting that first response when I post something I’m working on is always stressful, and it’s nice to hear something positive out of the gate! :smile:

Absolutely! Paths can be split by selecting them directly and using the “Split” button in the Inspector (will be shown off a bit later) or by selecting two Nodes that have a Path connecting them. I haven’t yet implemented it, but if people think it would be useful, I could provide a “Dissolve” function, too, to basically do the reverse of this.

I get what you’re saying. The movement stuff is very early in progress still, so I don’t have anything to show off there yet. The idea is to offer different schemes/settings to allow the system to function how the user wants, but also expose the API as much as possible to provide useful functionality for code outside the plugin.

So if you want to have a level select stage like Super Mario World, you could set that up using all the configuration settings. Or if you wanted to set up a system like FTL, where paths only work in one direction and events happen along the way, you can do that too (using the built-in settings).

But if you wanted to have a map like Overcooked, where all you needed to know was when the player was within a certain distance of a Node, pan the camera to show recently revealed Nodes, etc… you could set that up using the API rather than the built-in movement system.

1 Like

Pathfinding is now working! Paths between Nodes can be set to Two-Way, One-Way, or Impassable. Agents will move along those paths, respecting the allowed movement designation until they reach their target node.


Taking the path of least resistance


Taking the scenic route

Taking the detour

Currently, pathfinding uses the node’s object positions to determine distance and will look for the shortest route in that regard. I’m thinking of adding the option to disregard physical distance and calculate paths on least number of nodes as well, for maps that care more about the graph representation than the physical distance they’re displaying.

Hi!

I was looking if someone has made some asset like this (because I need to prototype something like this in my project) and suddenly I found this wonderful post! It looks amazing, and I can’t wait to see it released, do you have any ETA yet?

Also, I have a suggestion, can the ways that connect the nodes be curves that we can modify? If you need some reference, look at the maps in Final Fantasy Tactics Advance (or it’s sequel Final Fantasy Tactics A2), that way we can create more organic maps ^_^.

Good work! I’ll be following this post closely, and if you need some testers I’ll be glad to help!

Thanks for the kind words and expression of interest, @Targaryen ! (Fire and Blood!)

My second kid will be arriving mid-September, and I’d really like to have this released before then. In order to accomplish that, my plan is to divide features up into different releases.

First Release - 1.0 (Estimated September 15th, 2017)

  • Core tool set to create and edit node maps using Scene view and Inspector
  • Pathfinding between nodes
  • Player movement options using multiple input types
  • AI movement options
  • Subscribable events for map agents

Second Release - 1.1 (Estimated Q4, 2017)

  • More robust styling system for customizing map appearance
  • Spline-based path option for continuous (rather than current marker-based) routes
  • Curved paths
  • Additional included art for nodes, markers, and paths (suiting different themes like RPG, Space, etc)
  • Any technical enhancements requested since first release

I do really appreciate you mentioning you want the curved paths. That’s new territory for me, so I was debating whether it would be worth it, even. Keep the suggestions coming so I can ensure this asset is everything people want it to be!

Agent system is nearing completion, with two included player-type scripts and two AI-type scripts out of the box.

  • Click to Move (Player) - Clicking or tapping a Node will find a route there from the Agent’s current position. If a valid Route is found, the Agent moves to that Node.
  • Direct Move (Player) - Input from the keyboard or joystick is used to find a passable Path in that direction. If a valid Path is found, the Agent moves to the connected Node. This can be set to use world-space (Up corresponds to +Z axis) or camera-relative (Up corresponds to top of screen).
  • Patrol (AI) - The Agent is assigned a list of Nodes and will continuously cycle through them, moving to each Node in turn.
  • Wander (AI) - The Agent chooses a random Node on the Map and attempts to move to it. Upon reaching the target Node, a new random Node is chosen.

Agents also have a series of events that can be subscribed to and handled in your own scripts:

  • OnMoveStart - Agent has started moving
  • OnNodeArrive - Agent has arrived at Node. Note that this is not necessarily the final destination of the current move
  • OnMoveEnd - Agent has finished moving
  • OnCannotReach - Agent cannot reach target Node and will not move
  • OnAgentCollide (not implemented yet) - Agent has come into contact with another Agent
  • OnMarkerTick (not implemented yet) - Agent has passed over a path marker. Useful for systems that want to deduct fuel cost or increment timers for player travel

In order to demonstrate the different types of Paths, Agent move types, and events, I’m putting together a demo scene that I think will be quite useful:


Moving one Agent with the keyboard and another with the mouse was trickier than I anticipated

If anyone has specific requests for events or movement types not covered, now’s the time to make them. I mostly plan on cleaning things up, enhancing the Inspector UI a bit, and documenting everything at this point before the first release.

1 Like

I think this is good now.
so is it possible to just assign a target node in the Click-to-Move or Wander script (I’d probably be using some waypoint-control script for that)

suggestion:
might be a check if the agent is able/allowed to pass through a path section
(impassable may be impassable for some, passable for others : but better would be for all path types)

also, Two-Way is the small circle nodes? must be, just wasn’t clarified

If you’re rolling your own movement system, you won’t need the ClickMove or Wander scripts attached to your agents at all. You’ll just access the Agent component and call its methods directly, in this case, MoveToTarget(Node targetNode). MoveToTarget also has an overload which accepts a string parameter which will search for a Node by that name and move to it.

Yeah, as of yesterday, there was one setting for a path that would be used for all Agents. I can see how it’d be useful to allow certain Agents through and others not, though. So I’m working on adding that in today. It’s not fully fleshed out yet, but my current thinking is that each Map will maintain a list of AgentTypes (strings) that can be assigned to Agents of that Map via a dropdown. Each Path has a default movement setting (Two-Way, One-Way, Impassable) with the option of adding overrides. An override is a set of AgentTypes and Movement types, so you can set custom movement rules for each type, if you like. But if no override rule is found for an Agent’s type, it will use the default.

Does that make sense?

In my case, yes. I should also point out that the marker appearance (Cheerios, Arrows, Xs) are a separately assignable visual property than the movement type. That makes it kind of annoying to switch lots of paths over from, say, two-way to one-way, but it affords more flexibility. In FTL and Super Mario Bros 3, for example, the paths themselves don’t indicate whether you can move on them or not, but rather (specifically, Mario) the state of the current Node you’re one would. I’m still wracking my brain trying to think of what the right compromise is to this, but haven’t come up with anything yet.

Quick update to round the night out:

Thanks to @dibdab 's suggestion, I added in the ability to override a Path’s movement type. I also made a few other tweaks and mods based on to accommodate all this. Rather than just talk about it, let’s use this opportunity to take our first look at the custom Inspectors that have been a surprisingly large amount of the time I’ve put in so far.

Forgive the rough appearance and inconsistency with column widths, colon presence, etc. This is the most I’ve delved into Editor scripting, and I’m learning a lot here. :smile:

The Map

The Map, being the root of any Node Map, has some settings you’d expect to see applied across the board. This is also where you can set defaults that new Nodes and Paths will honor (though these settings will not affect existing items).

New tonight is the “Agent Type” list, which allows you to add a set of tags that can be applied to your Agents. I kinda hate relying on Unity’s built-in tag system because I’m never sure how it’ll work for someone else’s project. Anyway, each Agent can (and must) have one tag applied to it.

Nodes

Nothing much to talk about here, except each Node’s inspector allows you to view at a glance all Paths going to and from it. You can also quickly jump to editing those Nodes by using the Select button here.

Paths

Here we see the Path details, including what Nodes it connects, and what kind of movement it is. In addition to the previously mentioned “Two-Way”, “One-Way”, and “Impassable” types, I’ve added “Reverse” to the list, which is just a One-Way that operates in the opposite direction. I honestly can’t think of when this would be needed, but it never hurts to provide the option, right?

I’ve also implemented a cost multiplier for both directions. So you may have a Path that from the foot of a mountain to its peak. The ‘From’ cost can be higher to indicate that direction of travel is more intensive. This is used by the Pathfinding system when determining F-cost, but you can also get creative and use it in your game by reducing player resources at a higher rate.

Anyway, right there in the center was most of today’s work: Overrides. Adding an override creates a new item where you can pair an Agent type (defined in the Map) and a movement type (One-Way, Reverse, Two-Way, Impassable). For this Agent type, the path will be evaluated on that type. So what may not be passable for other nodes, could be passable for this, and of course, vice versa.

I’m really torn about adding cost into the override. I already had to rewrite half of my pathfinding stuff tonight, so I’m not stoked about having to go back and add more complexity to it, but maybe I’ll feel differently once my brain has rested.

Oh, and you may have noticed I also added a new marker type: Dash.

Oh, I also have the OnAgentCollide and OnMarkerTick events fully working now.

Project Status
I’d say I have things 90% complete, functionality-wise. I started writing the manual last night, but will have to go back and change a lot before I’m done with everything I’ve added. (Tip for others and future me: Probably best to wait to write the manual until it’s 100% done…)

I want to say I may be well early of my intended release date, but by the time I get everything cleaned up, documented, tested, packaged and approved, it may be closer to September than the current date. Time will tell, but if I can keep up this pace, I’m very optimistic the wait won’t be long.

okay, but is this the destination node or the next node? I need the next node along the path, to rotate/choose anim/etc. for my character.
or this function produces/provides the nodes along the path?

so these path scripts are added automatically, when you organize the nodes/paths in the editor?
it’s very similar to the waypoint-system I started to make (and how node path-system I’ve seen work), but of course this is more advanced.

it’s good, just please make a function so it is possible to add override from another script too. (and then it could be altered realtime)

The way it works currently, Agents have a public Queue of Nodes when they’re on the move. You can listen for the OnMoveStart and OnNodeArrive events, and then Peek at the top of the Queue to get the next Node’s transform. The OnMoveEnd event will let you know when you should stop animating your movement. If you think it’d be helpful to have other events (or a different way of handling this), let me know.

Edit: Now that I’m reading this, I think it would be smart to provide a CurrentMoveTarget property that accesses the next item in the Queue for you. Consider it added.

Yep, when you add new Nodes and create Paths, the scripts are added automatically with the appropriate configurations passed into them.

I think what you’d want to do is have another script attached to the same object as the Agent. Get a reference to the Agent component in your script and call the MoveToTarget method from there. Is there a different way you’d like to be able to do this?

1 Like

I think there’s a slight misunderstanding. in the last section I was talking about override
add override from another script too. (and then it could be altered realtime)
for this
3174948--241967--override.jpg
it would be good for (quick example):
if an area is flooded

1 Like

Ahhhh! That makes more sense. That’s definitely possible to do currently. I’ll be sure to add helper methods and document it thoroughly, since this seems like something people would potentially want to do a lot of. Thanks for mentioning it!

Documentation is basically complete. Just have to add a bunch of screenshots, and postponing that until I’m sure I’m done messing with the UI stuff.

Last night I implemented the ability to pause and resume movement for Agents individually, or for the entire Map. I also added a function to allow an Agent to cancel its movement and retreat back to the last Node it reached.

With that are three new events: OnRetreat, OnPause, and OnResume.

I have a few outstanding bugs I need to squash, and potentially one last feature. After that, it’ll be time to start packaging things up!

So close to being finished, but a weird bug has cropped up in the Wander movement script that makes the Agent pick up speed with each target Node arrival. After a few iterations, it starts going ballistic.


Slow down! This is a neighborhood!

I have a few other little creeping issues, mostly serialization-related and problems when code that’s only supposed to run in the Editor somehow finds its way into Play mode (curse you, OnDestroy!) but overall I’m very happy with the functionality set I’ve gotten worked in, and once these last few bugs are eliminated, it’s time to start wrapping presents.

Hi!

It’s amazing how in a few days it has improved so much!!

Still, I bring a few suggestions that I don’t know if you’ve considered, first, I’d like to know if there’s a “teleport” system, with teleport I mean some function that lets me place the agent in the node that I want without moving through the node web, this is mainly used for when I want to load the game and set the position of the agents to their node they were when I saved it, if they have to move to its position, it can be weird, and if I move it in a node but comes back to its initial node, it’s a bit useless…

Also, I’ve seen you’ve made some events! What I want to know it’s if those events return the node the agent is in, this especially important for OnMoveEnd/OnNodeArrive, as I’ll probably have custom code in every node, and the agent will have to do different things depending on the node that it has arrived; Another thing that it occurs to me, it’s that OnNodeArrive should distinguish if it’s the final node or not, that way there’s an event for the nodes in the middle of the path, and another one when it reaches the end.

And that’s it for now, I bet that once I start prototyping, I’ll find more things that can be added, but first, I’ll have to start dwelling in the whole “map manager”, and try what’s the best way to manage what’s in the nodes, what are the events on the map, and what’s the best way to combine multiple maps (like the layered mecanim system… but with maps), and by this point If you haven’t played Final Fantasy Tactics A2, you should at least see how the exploration works, it has the most complex system I can think of, and my first goal it’s to try to replicate it with your asset, so if you think your asset can do all that game does, then it’s set to go! :smile:

Good luck fixing those nasty bugs!
See ya!

Thanks! The feedback from the two of you has definitely been helpful in that regard!

Always welcome! Even once I’ve packaged it up and sent it off for approval, I can get started on 1.1 features or quick fix items for a minor release.

Absolutely. Agents have a JumpToNode(Node targetNode) method that does exactly this. I don’t have the screenshots in it yet, but if you’re interested in peeking at the WIP manual, I can send you a link privately.

They sure do. OnMoveStart, OnMoveEnd, and OnCannotReach all pass a reference to the target Node. OnNodeArrive passes the Node just arrived at. OnRetreat passes the previously occupied Node (which is now its new target).

That’s a good point I hadn’t considered. While you could compare if the Node passed by OnNodeArrive is the Agent’s publicly accessible targetNode, how about if instead OnNodeArrive also passed along a boolean indicating if it’s the target Node or not?

I’ll definitely look into it. In my head, I can picture how this system could make a wide range of maps, but I’m sure potential (and even necessary) enhancements will reveal themselves once it’s actually out in the real world.

Stay tuned!

Good news, everyone!

Node Map is now available on the Asset Store!

I’ve got some contract work to look into for a friend, but once that’s tied off, I can begin work on the 1.1 feature set. Hope you’ll all find this package useful!

just started looking at it

how would I join two nodes?
3202160--244808--joinnodes.jpg

I found in the manual

how to select multiple nodes?

the other thing, how would I use

FindValidPath (Node a, Node b)