I want to add a simple enemy that will chase the player if they’re near. But i also want for it to wander from their current position to a random position. But i can’t get it to work. Here’s the code:
extends CharacterBody3D
@onready var player = get_node("/root/Node3D/Player")
var gravity = 3
var Speed = 70
var Health = 3
var wander_cooldown = 0
var chase = false
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += -gravity * delta
if chase == true:
position += (player.position - position) / Speed
$AnimationPlayer.play("Walk")
else:
$AnimationPlayer.play("Idle")
wander_cooldown += delta
if wander_cooldown == 2:
wander()
move_and_slide()
func _on_see_body_entered(body: Node3D) -> void:
if body.is_in_group("Player"):
chase = true
func _on_see_body_exited(body: Node3D) -> void:
if body.is_in_group("Player"):
chase = false
func _on_hitbox_body_entered(body: Node3D) -> void:
if body.is_in_group("Player"):
if player.Health > 0:
player.Health -= 1
player.hurting()
if player.Health == 0:
player.eye_egg_death()
player.mauled_death()
$Timer.start()
func _on_hitbox_body_exited(body: Node3D) -> void:
$Timer.stop()
func _on_timer_timeout() -> void:
if player.Health > 0:
player.Health -= 1
player.hurting()
if player.Health == 0:
player.eye_egg_death()
player.mauled_death()
func wander(): #the func i need help with
var random_wander_position = randf_range((position.x - randi_range(0, 10) + position.z - randi_range(0, 10)), (position.x + randi_range(0, 10) + position.z + randi_range(0, 10)))
for x in (random_wander_position - position):
position += (random_wander_position - position) / (Speed + 10)
It might never be exactly 2 due to how float numbers work, so your wander() function might never trigger. You’re also never resetting the cooldown. It should be:
Then in your wander() function, I honestly don’t understand what’s happening. Ideally, you shouldn’t directly change the position of your enemy, you should adjust its velocity and let the move_and_slide() function do the work for you. The same as you did with the gravity.
Here’s the code I use for my Creatures that wander about randomly unless triggered to ‘chase’ the Player. Obviously much of the external code, in other Global sections, isn’t shown, but the meaning should be pretty clear, I hope…
func move(delta):
if not lv_dead and not lv_hit:
if lv_shape_cast.is_colliding():
rotate_object_local(Vector3(0, 1, 0), deg_to_rad(150))
if lv_chase == true:
var lv_player = GlobalVariables.gv_curr_play
look_at(Vector3(lv_player.global_position.x,self.global_position.y,lv_player.global_position.z), Vector3.UP)
self.rotate_object_local(Vector3.UP, PI)
var lv_vec_to_player = lv_player.position - position
lv_vec_to_player = lv_vec_to_player.normalized()
var lv_g_vec_to_player = lv_player.get_global_transform().origin - get_global_transform().origin
lv_g_vec_to_player = lv_g_vec_to_player.normalized()
move_and_collide(lv_vec_to_player * lv_spee * delta)
else:
lv_frame_count += 0.5
if lv_frame_count < lv_random_number:
move_and_collide($Armature.global_transform.basis.y.normalized() * lv_spee * delta)
else:
rotate_object_local(Vector3(0, 1, 0), -lv_random_turn)
new_rand_numb()
lv_frame_count = 0
move_and_slide()
func new_rand_numb():
lv_random_number = lv_rand_numb.randi_range(50, 120)
lv_random_turn = lv_rand_turn.randf_range(deg_to_rad(-45),deg_to_rad(45))
Ask, of course, if clarification is needed. Hope this helps.
there’s an error message if i try to use it (also i think there’s something wrong with my random position thing and it makes it not work. I am a beginner developer)
I always use static typing for my variables, but because you aren’t this needs a small adjustment:
The issue is that Speed doesn’t have a static type and thus the type for horizontal_velocity can’t be inferred. Manually type hinting horizontal_velocity should fix this error:
var horizontal_velocity: Vector3 = position.direction_to(target_position) * Speed
About your target position: This needs to be a Vector3 (currently it seems to be just an integer). And I would probably separate the random offset from the initial position, though this is just personal preference:
var target_position: Vector3 = position + Vector3( randi_range(-10, 10), 0, randi_range(-10, 10) )
(This is not identical to your calculations because it doesn’t convert the current position to int, so if that was intended just use your calculations for x and z of one Vector3 instead.)