Gdscript is being slow

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jujumumu

I have a lot staticbodies all checking if the player is in range the fps drops to 6 and the game is really slow. If I use c++ plugins will it be much quicker since it is compiled?

extends Area2D
func _on_Detector_body_entered(body):
      if body.name=='Player':
            //do thing

This is all the code I have for the staticbodies

Examples is when there are 250 staticbodies and the fps drops to 6, the process goes really fast at 0.003s, and the physics process increases to 0.3.

Show your code, you may be doing something very inefficient.

kidscancode | 2019-08-06 23:53

I added the code

jujumumu | 2019-08-07 00:51

:bust_in_silhouette: Reply From: fngreg7

So without more context, I have a shot in the dark. All 600 of your objects are checking each other as well as for the player. That’s like 600^2 calculations since the areas likely overlap each other on the StaticBodys. I know you want to do a thing if player, but that evaluation still has to happen for every overlap of every area…

:bust_in_silhouette: Reply From: Skipperro

Without more code I cannot say much, but I had a similar problem with pathfinding. Maybe you can adapt my solution to your problem too.

My problem was, that I had a bunch of BadGuys on the map, each calculating path to the player each frame. If there were more than 5 BadGuys, FPS dropped to single digit.

The solution was, to build a dedicated node with a script, that calculates paths from BadGuy to Player on a separate thread, and when calculation is done, it sends signal to BadGuy with updated path. This way performance is constant and if there are many BadGuys, only update-rate drops (AI have slower reaction time), not FPS.

Maybe it will help you. To say more, I would have to see the whole code.

Can you show your code so I can edit and use it

jujumumu | 2019-08-08 23:38

Sure… It’s more than a few lines and it’s not the cleanest code, as it was created with great deal of experimentation and I haven’t refactored it yet, but this should give you a glimpse of what is going on.

Focus on pathfinder variable.

This is a controller script:

extends Spatial

export var maximum_enemies = 50
var Counter = 0
var pathfinder = Thread.new()
#var spawner = Thread.new()
var enemies_to_command = []
var threaddata 
var mutex = Mutex.new()
var charge_mode = 0.0
var nav

func _ready():
	nav = get_parent().get_node("Navigation")

func _physics_process(delta):
	charge_mode += delta
	if charge_mode > 10.0:
		charge_mode = 0.0
	if not pathfinder.is_active():
		var PLAYER = get_parent_spatial().get_node("Player/KinematicBody")
		var player_pos = PLAYER.get_global_transform().origin
		enemies_to_command.clear()
		for enemy in get_children():
			if enemy.has_method("_UpdatePath"):
				if not (enemy.dead):
					if enemy.last_gps_update > 1.0:
						enemy.last_gps_update = 0.0
						enemies_to_command.append([enemy.name, enemy.get_node("KinematicBody").get_global_transform().origin, player_pos])
		pathfinder.start(self, "_async_pathfinder", enemies_to_command, 0)

func _async_pathfinder(data):	
	for e in data:
		var start = e[1]
		var end = e[2]
		var enemy_name = e[0]
		var pathvect = nav.get_simple_path(start, nav.get_closest_point(end), true)
		var path = []
		if pathvect.size() == 0:
			path = [end, end, end] # Fallback
		else:
			path = Array(pathvect)
		call_deferred("send_to_enemy", [enemy_name, path])
	call_deferred("_async_pathfinder_completed", [])

func send_to_enemy(commands):
	if has_node(commands[0]):
		get_node(commands[0]).call_deferred("_UpdatePath", commands[1])
		
func _async_pathfinder_completed(path):
	var results = pathfinder.wait_to_finish()

func _on_Commander_timeout():
	if pathfinder.is_active():
		return false
	pathfinder.start(self, "_async_pathfinder", [])

On BadGuy Nodes:

var gps_points = []
var dead = false
var last_gps_update = 5.0

func _UpdatePath(path):
	if dead or disposable:
		return false
	if path.size() > 2:
		gps_points = path

Skipperro | 2019-08-09 05:48

I found out it is not because of the intense calculations it is the number of rigidbodies.

jujumumu | 2019-08-09 17:24

:bust_in_silhouette: Reply From: Zylann

Considering just the code you shared, I don’t see any reason why GDScript would make things slow.
The 2D physics engine, however… might be.
But hard to be sure without seeing the full test project.

The physics process is really slow I added a example. How can I fix this?

jujumumu | 2019-08-07 17:29

Still can’t guess what’s going on. The problem lies outside of the code you shared.

Zylann | 2019-08-07 18:22

Why does the problem lye outside? If it does how could I fix it and my game is pretty large so it would be hard for me to share all the code. A observation I made is that upon impact with the ground the game gets more lag, the physics process speed stays the same but the fps drops very low and the _process is really really slow.

jujumumu | 2019-08-08 14:04