Enemy speed depends on distance from target. How do I fix this?
Asked Answered
A

6

0

I'm trying to make the enemy move towards either the player or a ball in my 3D football game, but I keep encountering an issue where the enemy will become faster or slower depending on the distance from the ball, and obviously I don't really want that as they can become unnaturally fast and cause lag.

Here is the code for finding the ball:

func _process():
                       if ball_detected:
				target = ball_identity
				mode = "chasing_ball"
				speed_multiplier = 0.5
				var pos = target.translation
				var self_pos = self.translation
				var look_at_me = Vector3(pos.x, 0, pos.z)
				#print(look_at_me)
				look_at(look_at_me, Vector3.UP)
			else:
				target = self
				speed_multiplier = 0
				mode = "idle"
		move_to_target(delta)

And then here is the code to move the enemy:

func move_to_target(delta):
	var direction = (target.transform.origin - transform.origin).normalized() #sets the direction
	direction.y = 0 #this is to prevent the enemy from floating, as I has encountered this before
	move_and_slide(direction * speed * speed_multiplier * delta, Vector3.UP) #moves the enemy

Any help is greatly appreciated 🙂

Avelinaaveline answered 31/3, 2023 at 11:10 Comment(0)
P
0

When writing code add ``` before and after it.

Principally answered 31/3, 2023 at 11:31 Comment(0)
A
0

Principally oh thanks

Avelinaaveline answered 31/3, 2023 at 12:9 Comment(0)
H
0

Can we have more code for context? I also want to know what type of node you're using Kinematic/Rigidbody/Node3D

Heptameter answered 31/3, 2023 at 12:35 Comment(0)
A
0

Heptameter here's everything before and including the move_to_target function:

extends KinematicBody

onready var raycast = $RayCast

var speed = 500
var target
var speed_multiplier = 1
var mode = "idle"

var team

var goal_attacking
var goal_defending

var starting_y_level = 1.5
var starting_rotation = 0

var stunned = false
var ball_identity = null
var on_ball = false
var in_tackling_range = false
var ball_detected = false
var enemy_detected = false
var enemy_detected_closer = false
var refreshing = false
var updating = false
var looking_for_goal = false
var direct_line_of_goal = false

var identities_in_area = [null, null, null, null, null]
var identities_in_closer_area = [null, null, null, null, null]
var total_identities = [identities_in_area, identities_in_closer_area]

var reaction_speed = 0.25
var tackling = 50

func _ready():
	check()
	closer_check()
	yield(get_tree().create_timer(0.1),"timeout")
	set_goal_targets()
	#refresh_cycle()

func check():
	yield(get_tree().create_timer(reaction_speed), "timeout")
	if Global.identity_on_ball != null:
		enemy_detected = check_for_identity(Global.identity_on_ball, 0)
		if enemy_detected:
			target = Global.identity_on_ball.get_node("future_pos")
	check()

func closer_check():
	yield(get_tree().create_timer(reaction_speed), "timeout")
	if Global.identity_on_ball != null:
		enemy_detected_closer = check_for_identity(Global.identity_on_ball, 1)
	closer_check()



func update_rotation(target):
	if updating:
		pass
	else:
		updating = true
		yield(get_tree().create_timer(reaction_speed), "timeout")
		look_at(target.global_transform.origin, Vector3.UP)
		updating = false
		

func stun(length):
	stunned = true
	yield(get_tree().create_timer(length), "timeout")
	stunned = false


func _physics_process(delta):
	translation.y = 0


func _process(delta):
	if !stunned:
		if Global.identity_on_ball != null:
			$ball_detection/CollisionShape.disabled = true #somebody is on the ball
			if on_ball:
				ball_identity.global_transform.origin = $feet_area.global_transform.origin
				#$feet_area/CollisionShape.disabled = true
			else:
				ball_identity = null
				#$feet_area/CollisionShape.disabled = false
			#enemy_detected = check_for_identity(Global.identity_on_ball)
			if enemy_detected_closer:
				mode = "chasing"
				target = Global.identity_on_ball
				speed_multiplier = 1.5
				var pos = target.translation
				#var self_pos = self.translation
				var look_at_me = Vector3(pos.x, pos.y, pos.z)
				look_at(target.global_transform.origin, Vector3.UP)
				rotation.x = 0
			elif enemy_detected:
				#print("enemy detected")
				mode = "chasing"
				#target = Global.identity_on_ball
				speed_multiplier = 1.1
				var pos = target.translation
				#var self_pos = self.translation
				var look_at_me = Vector3(pos.x, pos.y, pos.z)
				look_at(target.global_transform.origin, Vector3.UP)
				rotation.x = 0
				#update_rotation(target)
			elif Global.team_on_ball != team:
				mode = "retreating"
				speed_multiplier = 1
				target = goal_defending
				var pos = target.translation
				#var self_pos = self.translation
				var look_at_me = Vector3(pos.x, pos.y, pos.z)
				look_at(target.global_transform.origin, Vector3.UP)
				rotation.x = 0
			elif on_ball:
				check_collision()
				mode = "attacking_on_ball"
				target = goal_attacking
				speed_multiplier = 0.5
				var pos = target.translation
				#var self_pos = self.translation
				var look_at_me = Vector3(pos.x, pos.y, pos.z)
				look_at(target.global_transform.origin, Vector3.UP)
				rotation.x = 0
			
			else:
				#print("target self")
				target = self
				speed_multiplier = 0
				mode = "idle"
			
		else:
			$ball_detection/CollisionShape.disabled = false #ball is free
			if ball_detected:
				target = ball_identity
				mode = "chasing_ball"
				speed_multiplier = 0.75
				var pos = target.translation
				#var self_pos = self.translation
				var look_at_me = Vector3(pos.x, pos.y, pos.z)
				look_at(target.global_transform.origin, Vector3.UP)
				rotation.x = 0
			else:
				target = self
				speed_multiplier = 0
				mode = "idle"
		move_to_target(delta)



func move_to_target(delta):
	#print(rotation.y)
	var direction = (target.transform.origin - transform.origin).normalized() #sets the direction
	direction.y = 0 #this is to prevent the enemy from floating, as I has encountered this before
	move_and_slide(direction * speed * speed_multiplier * delta, Vector3.UP) #moves the enemy

It uses a KinematicBody3D btw
Thanks for your interest 🙂

Avelinaaveline answered 31/3, 2023 at 15:33 Comment(0)
H
0

I think it might be down to you using translation is the most immediate thing I can think of, I found this reddit thread that explains the differences well.

Instead because you want to have more control over your node, I would potentially use lerp_interpolate() ( Godot 3 ) or lerp() ( Godot 4 ) or change the position constantly using += among other things for a more instantaneous approach like you do for standard sidescrollers or top down.

Heptameter answered 31/3, 2023 at 15:57 Comment(0)
C
0

Avelinaaveline 3 things look problematic:

Your code changes the velocity direction vector after normalizing it. It should be done before normalizing. Otherwise its length will always vary and will unlikely be 1

move_and_slide() expects a velocity vector as the first argument. You're giving it velocity vector multiplied by delta. This will result in incorrect behavior.

move_and_slide() internally works with default physics engine delta time. Because of that it should only be called from _physics_process(). You're calling it from _process().

Companionate answered 31/3, 2023 at 18:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.