This site is currently in read-only mode during migration to a new platform.
You cannot post questions, answers or comments, as they would be lost during the migration otherwise.
+3 votes

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.

in Engine by (455 points)
edited by

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

I added the code

3 Answers

+2 votes

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...

by (24 points)
+2 votes

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.

by (207 points)

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

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

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

+2 votes

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.

by (29,510 points)

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

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

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.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.