Nav Mesh

A list is a set of entries of a certain length. You can find out how long by using len(list). The first entry is at position [0] and the last one is at [length -1] you can get the entries by using numbers in square brackets or variables that represent numbers. So if current_node =5 then list[current_node] will get the 6th entry on the list unless the list is shorter than 6 entries in which case it will give an out of range error.

That’s why it’s easier to pop entries until you have an empty list. Then you can use list[0] continuiously but you’ll still have to use an if list argument to avoid an error at the end.

I know next to nothing about vector math either but I do know that you can add or subtract a vector from a world position to create a new worldPosition, in effect moving the object in the same way dloc does in the movement actuator.

@Smoking_mirror
Thanks. But I still don’t get why the variable did not work because I used it in the same way that you used the property.

Did you remember to do current_node += 1? I sometimes forget to increment an index and the result is a frozen script, but it’s easy to fix.

Hi, I had an intense migraine yesterday so I couldn’t really look at your example.

After looking at your script I’m pretty sure you know more about programming than I do, so sorry if my explanations are sometimes a little condescending, If I don’t know how much someone knows I end up explaining everything.

Looking again at your script and the Blend files you posted it looks like you’re trying to match up the objects on two axis at the same time. It’s something I’ve done before when I didn’t know a better way (actually I was trying to line up a targeting reticule with the screen position of a target and there was no way of setting the screen position so I had to incrementally adjust the world position until it just about matched the screen position of the target). It is possible, but you should match the x position first, and then match the y position.

Anyway, it’s far better to use vectors, that way you can be more accurate and direct.

For the structure of you code you need something like this:

if you've reached the end of the list:
    finish
else:
    if the current node is close enough:
        make the next node the current node
    else:
        move closer to the current node

Whether you pop the list, or whether you increment an index, or whether you move using vectors or by incrementally adjusting the x and y world position shouldn’t matter to the above structure.

I usually insert some print statements in to my code when testing new structures to find where it is failing. In the above case I’d do this:

if you've reached the end of the list:    
    print ("finished")
    finish
else:
    if the current node is close enough:
        print ("node_reached:" + str(current_node.name))
        make the next node the current node
        print ("moving to next node:" + str(current_node.name))        
    else:
        print("moving..." + str(own,worldPosition) + "/" + str(current_node.worldPosition))
        move closer to the current node

That will give you feedback about what state the code was in when it failed. Sometimes knowing that will tell you what failed in the code and what didn’t.

@Smoking_mirror

Thanks for the compliment and all I really appreciate it.
You are amongst the most the oldest members of the forum I doubt I know more than you about anything.

P.S how is it going with the tutorial project?

My wife is going to be having another baby, so my projects are limited at the moment to things which I can do solo. I don’t want to drag other people in to a project and then have to jump ship as soon as the little’un pops out. I know from the last one that there’s be a few months where I’m just too busy to do anything, including sleep. :frowning:

But for now I’ve got a bit of time to muck about on some experiments of my own, and offer help or advice or suggestions to anyone who needs it.

Hi I hope you are having a good day.

@Somking_mirror
All the best to you and the little one.

Below is a blend file which is identical to the one Smoking_mirror posted in post 18, the only difference is the fact that I created the “current_node” property using Blender Python API and not the Blender GUI.
Why do the two properties act differently? Is there something I did wrong or is this how things are suppose to be.
Note: I tried using a variable to represent the “current_node” but it did not work(I describe the problem in post 22).

Thanks. Any Help and Solutions will be greatly appreciated.

The Blend didn’t get posted, but I can suggest using the following code to add properties:

if "current_node" not in own:
    own['current_node'] = 0

This first checks if the property exists, and then if it doesn’t already exist it adds it.

You may have been trying to add the property more than once, or there may have been other problems such as adding it as a string or float.

The following wouldn’t work:

if "current_node" not in own:
    own['current_node'] = 0.0
if "current_node" not in own:
    own['current_node'] = "0"
own['current_node'] = 0

I’ve tested it and it works fine. I’m also working on some path following scripts for my own project so I’ve got more examples if you need them.

@Smoking_mirror
Thanks a bunch that worked well. Any suggestions on how to do the same thing using a variable.

Well, if you use a local variable it will be rewritten every time the script executes. You only want to update the variable when the object reaches the waypoint. It’s best to use a property, though you could store it in a global dictionary if you wanted.

FollowPath_slerp_local_velocity.blend (518 KB)

Here’s a blend which uses an alternative to alignToVect, hopefully you can get something out of it.

@Smoking_mirror

Thanks, I really appreciate the help.

No problem.

Actually there’s a couple of ways to do this, one is as I’ve done it which is to update every logic tic. That’s a bit intensive and could get processor hungry if you’ve got a lot of agents. It’s also only really good for non-physics based games and works best with a data driven program rather than the usual Blender Object orientated programming.

The other way to do it would be to use a collision sensor and actually place blocks at the node co-ordinates. You could set up a “track to” actuator and a movement actuator and let blender’s built in physics based simulation go to work. Then you only need to update the track to target when there is a collision with the active node. That’s actually slightly faster to process because of the compiled nature of logic bricks. You don’t have to set the always sensor to pulse mode, the built in logic will control everything for you.

It’s up to you how to structure your project but that should be one of the first things to decide, whether you’re going to work with Blender’s inbuilt physics or if you want to control everything yourself. Data driven approaches do have some advantages, namely that you can better control large groups of agents to handle group AI better (with things like formations and tactical movement) but the emergent behavior approach of Object orientated programming is able to produce some pretty intelligent seeming AI behavior using simple rules and states.

Different approaches may be better suited to different game genres too. For example a history sim like Civilization or a RTS like red Alert would benefit from a data driven approach, while a FPS or racing game would be better to use real world physics and autonomous agents.

I’m going to be using this one in both a RPG and an RTS game so Iv’e opted for the data driven approach.