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
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.
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
-> get a random direction
-> get a random time
(both can be done with random actuators)
-> switch to state “going”
-> 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”
-> 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