Wandering Enemy

How do I make an enemy “Wander”? it’s easier said than done, I know. What would be the most effective way?

AI is a complicated thing. You say ‘wander’ but what does this mean?
One way to do it is for your AI to pick a random direction, and walk in it for a random length of time. What if there’s a wall there?
Another way is to use a NavMesh. This is a built-in blender utility and there are heaps of tutorials over the internet for it. With a navmesh, you can tell an AI to navigate to a particular location. If you want him to wander, you pick a random point for him to go to. This is easy with the python interface where you can simply set the target.

I’ve used navmeshes before, but only for path-finding and player-seeking actions, not wandering. I don’t really know how to randomly pick a point on the navmesh and go to it. might there be a tutorial on youtube? I couldn’t seem to find any

1 Like

I don’t think there are any tutorials on it. It is kind of assumed that by the time you want to have an AI, you’ve learned a bit of scripting and can read the API and get the necessary information from there.
Unfortunately, it never happens that way does it! I learned python to make an AI!

Pretty much all we have to do in python for wandering is to pick a random point. The easiest way to do this is to create a bunch of objects scattered around the navmesh for him to select one of. Let’s give them a property, say, ‘wander’

Then on the AI object, we can have the logic:
Always(pulse more on, time=120) -> Python -> navmesh (navigate, make the target objects one that exists. Make sure it is called ‘Navigation’. Set the velocity and turn rate to whatever you like.)

Then, this script will run every two seconds:

import bge
import random

cont = bge.logic.getCurrentController()
own = cont.owner

waypoints = [o for o in bge.logic.getCurrentScene().objects if 'wander' in o] #get a list of all waypoints in the scene
select_waypoint = random.choice(waypoints) #pick one randomly

cont.actuators['Navigation'].target = select_waypoint
cont.activate(cont.actuators['Navigation'])

This is pretty basic, but should work. I have not tested it.

There are so many ways to do this man, it just takes a little bit of thinking… You don’t even need python (though it’s preferred)!

My biggest advice:
Learn all you can about the BGE (logic bricks and python moslty).

It’s like math. You can’t solve any problem just by knowing the basics (adding and subtracting). You need more information in your knowledge base (Vectors, limits, trigonometry, etc). Once you do that you can look at harder problems and have an idea of how to solve them.

Everything becomes a lot clearer once you know what tools are at your disposal… and how to use them properly.

1 Like

Indeed the question is what you exactly do you mean with “wandering”.

What are the decisions and the resulting actions when you do “wandering”? If you know that you/we can transfer this to the BGE.

@Linkxgi: Yeah, I know there are many solutions to this problem. In fact, I had already solved this problem when I posted this thread. The problem is it’s too complex and has way too many logic bricks to be called “wandering” . I need something that is very effective and takes the least amount of “stuff”. I assumed Python was the easiest way to do so

@Monster: when I mean “Wandering”, I mean what asdgoff says in the second post. random walking direction for random time and turning

Add a boolean property (“move”) - and - steering brick to your object
Add an empty and set it as the target of the steering.
Then you add a boolean property (“randomize”)- python brick to the same object.
The python script will set the location of the empty to some random position and set the first boolean property to “True” to active the steering that will make the object follow the empty to the random location.
The script could look like:

import bge, random

def rdir(): return 2*random.random() -1#utility function

def main(controller):
    target = controller.owner#the object to move
    pos = target.worldPosition#current location of the object
    vec = pos.resized(3)#just to get a new vector to work with
    steeringTarget = target.actuators["Steering"].target
    vec[:] = (rdir(), rdir(), 0)#fill the vector with some random -1/1 values
    vec.normalize()#normalize to get a direction
    dist = 10 + 10 * random.random()#pick a random distance
    vec *= dist#create a translation along a direction
    destination = pos + vec#apply the translation to the current location to get a destination
    steeringTarget.worldPosition = destination#move the target of the steering actuator
    target["move"] = True#activate the steering actuator
    target["randomize"] = False#set up the property for a new round

You can also avoid entirely the logic bricks but a mix of script and bricks can get you out of trouble very fast.

This is quite precise.

I suggest to use states


“selecting”
-> get a random direction
-> get a random time
(both can be done with random actuators)
-> switch to state “going”
(state actuator)

State “walking”:
-> turn to the selected direction
-> go foward
-> start timer with the previously selected value (can be done in the other state too)
on timeout: -> switch to “select”

Alternative:


State “selecting”
-> get a random decision if walking or turning
-> get a random direction
-> get a random time
on decision “walking”-> switch to state “walking”
on decision “turning” -> switch to state “turning”

I hope you get the idea