FPS drops when enemies try to walk

Godot Version

4.3 stable

Question

Hello! I am making my first game to a gamejam, and I am having problems with fps drops when around 7 enemies try to walk.
I believe the problem is with my enemy movement code because when the enemies are stopped, the game runs fine

Here is enemy.gd code:

extends CharacterBody2D

var player_inside_vision: bool = false
var player: CharacterBody2D
var can_shoot: bool = true

const SPEED: float = 50.0

const ENEMY_BULLET = preload("res://scenes/enemy_bullet/enemy_bullet.tscn")

@onready var shoot_delay: Timer = $ShootDelay

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	if player_inside_vision == true and can_shoot == true:
		velocity = Vector2(0, 0)
		shoot()

func _physics_process(delta: float) -> void:
	if player:
		if player_inside_vision == false:
			var direction = (player.global_position - global_position).normalized()
			velocity = direction * SPEED
			move_and_slide()
		else:
			velocity = Vector2(0, 0)

func _on_shooting_distance_body_entered(body: Node2D) -> void:
	if body.is_in_group("Player"):
		player_inside_vision = true

func _on_shooting_distance_body_exited(body: Node2D) -> void:
	if body.is_in_group("Player"):
		player_inside_vision = false

func _on_player_reference_body_entered(body: Node2D) -> void:
	if body.is_in_group("Player"):
		player = body

func shoot():
	var bullet = ENEMY_BULLET.instantiate()
	bullet.position = global_position
	
	var direction = (player.global_position - global_position).normalized()
	bullet.direction = direction
	
	get_parent().call_deferred("add_child", bullet)
	can_shoot = false
	shoot_delay.start()

func _on_shoot_delay_timeout() -> void:
	can_shoot = true


The game is a top down shooter.

Any ideas on how I can fix this?

Do you have complex collision shapes?

You could speed this line up by using direction_to instead, but with only seven enemies it won’t do much; the script looks very simple, I’d bet it’s overly complex collision.

var direction = global_position.direction_to(player.global_position)
1 Like

In the Enemy scene, i have 3 collisions shapes. All of them are not “complex”? I think.

I just use the normal shapes: 2 of them are rectangles and 1 is a circle.

What about your world/player? Do the CharacterBody’s CollisionShapes use simple shapes such as Rectangles and Circles too?

Scaling a collision shape by 99 sounds really bad, Could you get your player reference from the shooting distance? You only use the player direction when they are “inside vision” anyways.

func _on_shooting_distance_body_entered(body: Node2D) -> void:
	if body.is_in_group("Player"):
		player_inside_vision = true
		player = body

The player has only one collision shape, its just a capsule.
I have only one tilemap with collision, and that is the grass one:

I don’t think i can, because i want my enemies to first walk to the player and then stop and shoot when the player is inside its ‘reach’

Ah I see, well you do have a “EnemySpawner” so I assume the player will be ready before any enemies are, you can get the player reference on _ready()

func _ready() -> void:
    player = get_tree().get_first_node_in_group("Player")

Tilemaps can be pretty dense collision, it should get better in 4.5, try out using StaticBodies with WorldBoudry CollisionShape2Ds since your borders are pretty square anyways.

1 Like

Oh yeah.. that’s is smart.
I deleted the PlayerReference area2d and put your code.

It appears to be fixed. I have 15 enemies in the screen walking without lag!

Thank you very much!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.