I am trying to get this AI figure to walk to the player, there is this code, I’ve read findplayer. The AI only faces the player, I removed state6 and changed it to state2 to avoid the AI attacking. In my example, the AI just needs to follow the player. navmesh.001 is the navmesh for the area, I am not sure what else I need to get this to do the task.
To have the enemy A.I. object follow / walk-towards the player, you can dynamically assign the Steering actuator called, “walk,” to target the player object.
if you need an artificial intelligence that - 1.patrols the location, 2.check if it sees the player 3. monitors the player if the player is detected - to patrol the location, you need a timer - by which you will determine the change in the behavior of the unit for example, when the timer reaches 50, create a local variable behavior = random.randint(0,10) and if behavior in range(0,5) assign to property unit own[‘tactics’]=‘patrol’ and check all objects in scene for search patrol points - for i in scene.objects: if ‘patrol_point’ in i and not i in patrol_list: patrol_list.insert(0,i), next, we randomly select an object from the patrol list and assign it as a target to follow - rand_point = random.choice(patrol_list), steering = cont.actuators[‘Steering’].target = rand.point cont.activate(steering). When the bot moves or stands still, it should check whether it sees the player - the radar sensor in conjunction with rayCast is well suited for this - if radar.positive:
obj = radar.hitObject
if ‘player’ in obj:
start = own.worldPosition
end = obj.worldPosition
ray = own.rayCast(end, start, 15, ‘player’)
hit = ray[0]
if hit:
if ‘player’ in hit:
own[‘tactics’] = ‘player_visible’
steering.target = obj
cont.activate(steering)
elif not ‘player’ in hit:
pass
remember one thing if the unit saw the player by throwing a beam and reached the player, you either have to do a distance check or disable the steering actuator otherwise the unit will ram the player’s collider - if you need to assign another navmesh, you can refer to it as a scene object by name if the name is known navmesh1 = scene.objects[‘navmesh1’] steering.navmesh = navmesh1 or by checking all objects in the scene through the for loop - for i in scene.objects:
if ‘navmesh’ in i:
steering.navmesh = scene.objects[i.name]
for check distance use dist = own.getDistanceTo(obj) or own.getDistanceTo(obj)>= or <= and never use ==
if own.getDistanceTo(player)<=5.000: #use rayCast function for check look line
Where does that snippet exactly go in that code? I wouldn’t know. Obviously no actual tutorial on this I think now from the file. It can’t be that difficult.
In findplayer.py, I’ guess, which is the following.
import bge
def main(cont):
cont.activate("walk")
cont.actuators["walk"].target = "player"
cont = bge.logic.getCurrentController()
own = cont.owner
#properties
direction = own['direction']
target = own['target']
cover_list = []
#sensors
cnear = cont.sensors['Cnear']
Ray = cont.sensors['Ray']
shootray = cont.sensors['shootray']
Delay = cont.sensors['Delay1']
#actuators
flare = cont.actuators['flare']
findP = cont.actuators['findplayer']
state1 = cont.actuators['State1']
#animations
fwd = cont.actuators['fwdwalk']
back = cont.actuators['backwalk']
left = cont.actuators['walkleft']
right = cont.actuators['walkright']
fwdfire = cont.actuators['fwdwalkfire']
backfire = cont.actuators['backwalkfire']
leftfire = cont.actuators['walkleftfire']
rightfire = cont.actuators['walkrightfire']
#sound
sound = cont.actuators['sound']
#walking
if target == '' and Ray.positive == False:
cont.activate(findP)
if direction == 'Run Forward':
cont.activate(fwd)
elif direction == 'Run Backward':
cont.activate(back)
elif direction == 'Run Left':
cont.activate(left)
elif direction == 'Run Right':
cont.activate(right)
#walking + firing
if target == '' and Ray.positive == True:
cont.activate(findP)
if direction == 'Run Forward':
cont.activate(fwdfire)
elif direction == 'Run Backward':
cont.activate(backfire)
elif direction == 'Run Left':
cont.activate(leftfire)
elif direction == 'Run Right':
cont.activate(rightfire)
#firing
if target == '' and Ray.positive == True and shootray.positive == False and Delay.positive:
cont.activate(flare)
cont.activate(sound)
if target == '' and Ray.positive == True and shootray.positive == True and Delay.positive:
cont.activate(flare)
cont.activate(sound)
own.sendMessage("Phit", "", "player")
if cnear.positive == True and target == '':
coverlist = cnear.hitObjectList
for i in coverlist:
if i['cover'] == 'safe':
distance = [own.getDistanceTo(i), i]
cover_list.append(distance)
cover_list.sort()
(own['target']) = cover_list[0][1]
if target != '':
cont.activate(state1)
movecover.py is just the AI moving and firing in their original locations, in my example, that doesn’t work, since I changed state6 to 2 or something.
I want the AI to travel to the player, so that is the new program for it to work.
If I understand this better, this would use the steering brick listed in layer 2 of the AI, so does the code go in findplayer.py
#walking
if target == 'player' and Ray.positive == False:
cont.activate(findP)
if direction == 'Run Forward':
cont.activate(fwd)
elif direction == 'Run Backward':
cont.activate(back)
elif direction == 'Run Left':
cont.activate(left)
elif direction == 'Run Right':
cont.activate(right)
import bge
cont = bge.logic.getCurrentController()
own = cont.owner
health = own['health']
crouch = own['crouch']
#knife
hknife = cont.sensors['hknife']
bknife = cont.sensors['bknife']
fknife = cont.sensors['fknife']
#bullet hit
feethit = cont.sensors['feethit']
bodyhit = cont.sensors['bodyhit']
headhit = cont.sensors['headhit']
#death states
headdeath = cont.actuators['headdeath']
bodydeath = cont.actuators['State4']
crouchdeath = cont.actuators['deathcrouch']
#hit animations
crouchhitAnim = cont.actuators['crouchhit']
bodyhitAnim = cont.actuators['hit']
#knife states
if hknife.positive and crouch == False or bknife.positive and crouch == False or fknife.positive and crouch == False:
cont.activate(bodydeath)
elif hknife.positive and crouch == True or bknife.positive and crouch == True or fknife.positive and crouch == True:
cont.activate(crouchdeath)
#headshot
if headhit.positive and crouch == False:
cont.activate(headdeath)
if headhit.positive and crouch == True:
cont.activate(crouchdeath)
#bodyshot
if bodyhit.positive and crouch == False and health > 1 or feethit.positive and crouch == False and health > 0:
cont.activate(bodyhitAnim)
own['health'] -= 1
if bodyhit.positive and crouch == True and health > 1 or feethit.positive and crouch == False and health > 0:
cont.activate(crouchhitAnim)
own['health'] -= 1
if bodyhit.positive and crouch == False and health == 1 or feethit.positive and crouch == False and health == 1:
cont.activate(bodydeath)
elif bodyhit.positive and crouch == True and health == 1 or feethit.positive and crouch == True and health == 1:
cont.activate(crouchdeath)
I tried editing this code Aihealth.py for player attack to AI melee longer duration, Knife states section changing the properties doesn’t do anything, I wanted to get the AI to be attacked a little longer with that action, instead of a ‘crouchdeath’
I am not sure if a timer is connected with state 4. Or the code needs some changing similar to a bullet hit animation change for the AI in the code.
I did change the AI property from 5 to 10. Not sure how much that would matter.
use property string for assign and change states and only one property timer or float
if own[‘behavior’]==‘knife attack’ and own[‘timer’]<10.000: #use attack knife and add for timer points
elif own[‘behavior’]==“knife attack” and own[‘timer’]>10.000: #change new behavior
yes right - not use states objects - because switching object states creates confusion, if you replace all states with a string, this will be the state of your object, which is more understandable and easier to read and correct logic errors.
if ['behavior']=='start_patrol':
for i in scene.objects:
if 'patrol_point' in i and own.getDistanceTo(i)>100.000:
obj = scene.objects[i.name]
steering.target = obj
cont.activate(steering)
own['behavior']='patrol'
if own['behavior']=='patrol':
for i in scene.objects:
if 'player' in i and own.getDistancetTo(i)<10.000:
start = own.worldPosition
end = i.worldPosition
ray = own.rayCast(end, start,0,"player")
hit = ray[0]
if hit:
if "player" in hit:
steering.target = scene.objects[hit.name]
cont.activate(steering)
own['behavior'] = 'track_to_player'
this is a very simple and primitive example of using a string as the behavior of an object - instead of logical logic blocks in the code, you always control the behavior itself and the properties of the object and the distance and the goal. For better control, you will need to create logic based on the behavior dictionary, but the behavior property for the object is still needed as well as the attack timer, you will have to write all this logic (I recommend code and not logic bricks) or look for examples here on blenderartist
A reminder to everyone on this thread: when sharing long blocks of code verbatim, please use the </> button on the formatting toolbar to format that code. It makes your code much easier to read and it also condenses it so scrolling on mobile is much less of a headache
Hmm, I am just trying to see what can be done with what there is there, i can upload the blend. Everything there is default, I haven’t added or changed anything, except one nav mesh I made for the area where I put the AI. In time, I may remove some parts of the level, if no real use. Everything is pretty much there, just needs AI and a design. I tried some files but they didn’t work for a different AI model.
As well changed one state to stop the AI from firing, I was thinking the AI may be punches the player, so not sure exactly what my idea was. Getting the AI to go find the player is one task, and getting the knife effect to last a little longer so the AI doesn’t just drop after one attack.
This is what I have so far. I am not sure what AI weapon actions.
#bodyshot
if bodyhit.positive and crouch == False and health > 1 or feethit.positive and crouch == False and health > 0:
cont.activate(bodyhitAnim)
own['health'] -= 1
if bodyhit.positive and crouch == True and health > 1 or feethit.positive and crouch == False and health > 0:
cont.activate(crouchhitAnim)
own['health'] -= 1
if bodyhit.positive and crouch == False and health == 1 or feethit.positive and crouch == False and health == 1:
cont.activate(bodydeath)
elif bodyhit.positive and crouch == True and health == 1 or feethit.positive and crouch == True and health == 1:
cont.activate(crouchdeath)
Could I not use this for the melee weapon?
If I add a new property to the player’s empty, it has
Add some sort of property change, so the knife has a similar programming to the gun, bullet here fires.
Agent find player if you make ray Cast from agent to player collider, walls, boxes and obstacles not detect, for this logic use find “player” property
for i in scene.objects:
if "player" in i and own.getDistanceTo(i)<=15.000:
player = scene.objects[i.name]
start = own.worldPosition
end = player.worldPosition
ray = own.rayCast(end, start, 0, "player")
hit = ray[0]
if hit:
if "player" in hit:
#player detect run logic track to player or attack
Navmesh use only path find to objects, for AI looking target(player, enemy, or player alliance) need make ray cast for check - visible or not target, if ray return player agent see player, if ray return walls, boxes, obstacles agent not vision player because see obstacle or use simply logic - in short distance enemy’s always see player just check distance and assign attack for agent
In the original FPS demo blend, the AI is attacking at a distance, and they slowly move, but they don’t actually get to the player in the navmesh area of the train station.
In my example one AI will move in the stairs area, which has its own navmesh. So can I use a brick for that AI, to simply find the player, while the python code would do any near detection and action/animation command to the player.
As is it stands, I don’t get the python, obviously I wouldn’t at least not all and everything. Could I not use a bit of python, like the example above, and use the bricks.