I want to optimize my npcs. The current doc says we can use Node3D, CharacterBody3D and Rigibody3D as actors. But the doc does not help to make choice regarding performance.
Basically the difference in code for moving the npc for each one is:
Actor as Node3D
global_position = global_position.move_toward(global_position + safe_velocity, movement_delta)
Actor as CharacterBody3D
velocity = safe_velocity
move_and_slide()
Actor as Rigidbody3D
linear_velocity = safe_velocity
What are the performance loss/gain depending on method we choose?
Do the Node3D is kinematic movement and the 2 others physic based movement? Rigidbody3D seems to act the same way as CharacterBody3D but just add move_and_slide() to handle walls, is that right?
How much move_and_slide() is for performance?
Is using CharacterBody3D still a good idea to have a maximum of npc (100+)? Is it possible to switch from kinematic to physics based method easily and is it recommanded ?
Let’s say there is walls, sidewalks and other agents/obstacles, is switching from kinematic to physics when near these obstacles a good idea?
The navigation and pathfinding does the same with all 3 choices so it is really not a navigation related performance choice.
From a pure performance perspective a basic Node3D is always superior because it does barely anything while both CharacterBody3D and RigidBody3D are full physics nodes with their own kinks and costly performance functions.
Oh sorry you are right, I should’nt have set the tag “navigation” in the question, as you said it’s not relative to it, about performance of this.
I am wondering how to know how much is the difference between Node3D and the other
I think there is no way around testing this in your specific project.
The reason is because a lot of the performance cost of those physics nodes depend on your physics layout and geometry.
E.g. a move_and_slide() stays “cheap” while your geometry is simple and you have little geometry stacked on top or close to each other.
Add a trimesh collision with a lot of faces and edges as “ground”, have a lot of actor stacked next to each other, have many areas nodes stacked that need constant updating, …your physics performance goes down the drain quickly with a few actors if you do all those things and the actual function will be just a symptom of your performance problems but not the actual cause.
In general CharacterBody is a “hero” node, it is designed for main actors like player characters as the sliding is more detailed but also very expensive. It does not scale well for performance if the game has a lot of actors using CharacterBody, e.g. it shouldnt be used at all for game types like RTS with e.g. 100+ actors active. Most RTS games dont use actual physics for the majority of the units outside of some ragdoll and explosions.
That’s interesting, actually my game is not an RTS but a city simulation with walking NPCs. Low-poly style for now. Do you think CharacterBody3D is not the best idea for this kind of game too?
Trimesh collision, stacked actors, this can be applied to my project as you describe it. I would like to make my own navigation mesh insead of being automatically generated, because for example so that a big plane place where there is some benchs and trees does not divide in way much faces that it needs between them when its flat. Between every obstacles, there is like 5 times more faces thanit could have if I was drawing it myself.
For a project like mine, I need NPCs walking, avoid obstacles/themselves, they may also be very close to the player so their movement needs to be realistic enough, this is why I like to use move_and_slide().
Actually my project can run with 30 NPCs CharacterBody3D around 60 fps, it’s ok because I am optimizing their position and destination near the player. But triple that number would be perfect.
Do you suggest RigidBody3D as a better option, or even Node3D? I still need some ground detection for walksides.
For a city builder type game imo CharacterBody is complete overkill, even using navigation mesh and NavigationAgent might be, as those game types barely even use any of the more complex pathfinding or physics solutions because it does not performance scale.
I think you are overenginerring for detail. If you look closer at most city builder games out there (some of them even have dev logs or talks, e.g. SimCity https://www.youtube.com/watch?v=eZfj7LEFT98&t=8s) they rarely use anything more than a mostly spline based waypoint system with a simple grid. E.g. you only need to swap some of them for more complex actors around the player while everything else runs a cheap simulation.
It’s not a city builder neither, it’s a bit my fault because I didn’t say the details, haha sorry.
My game is a business simulator like supermarket simulator except it is an other commerce. I need an immersive city, this is why I try to get same kind of npcs needs than supermarket sim.
Actually I created another navigation system for autos, that looks more like you said: a path given solution. But for npcs, as they may act like customers, and to avoid some mobile obstacles in my world, react, etc, I need the godot nav system. It suits good enough.
As I said I can have 30 npcs and as I optimized so they can all be near the player even if he moves, we can have every time the impression that there is a lot of npcs. But having more and optimize more is something I care and that could be a plus, or mandatory for slow pc.
For … let’s call them “shop simulators” … you use the normal navigation mesh system paired with a grid or slot system so that actors can “occupy” space.
If the “shop” is build with simple collision shapes for the bake geometry you can just rebake the navigation mesh every time an actor plans to stay a little longer in the same position or an object gets dropped or removed.
It only gets costly to rebake when you try to do that without any optimization for your entire level geometry or use visual meshes instead of collision shapes for the source geometry. If you level gets larger solve the performance by using a chunk system so that you dont need to rebake everything all the time.
When I looked in the godot debugger, I found that the biggest cost was the line “velocity = safe_velocity” from _on_computed_velocity(). So this is why I thinked it is due to the CharacterBody3D class. Am I wrong? What else can it be? Debugger can’t tell me more. The second biggest cost is Flush Queries and I can’t figure what is it about, as I don’t think I use queue_free() for npcs… I pool them, activate/deactivate/teleport when needed, no destroy.
Your optimization for space slot is interessting, I don’t think this reduce the fps more than the velocity issue, but that’s an optimization I may use later if needed.
Yes, I tried to rebaked, it was pretty fast ingame like few seconds or less. Problem was that even if the collision was a simple box, as my shop may be mobile (a truck), it can be in every rotation, but the navigation box obstacle doesn’t rotate, so the rebaked nav mesh do not match the actual shape/oriented of the truck but his shape without rotation (always along the same axis, never rotate with the truck). So instead I set multiple nav sphere obstacle (sphere radius), with area behind the truck that tells the customer to turn around the truck if entering it. That workaround is working fine, it’s not ideal but it’s ok.
My performance issue exists without the shop open (no customer) so it is not due to the nav mesh I think, but really the basic movment (velocity issue). And I’m not sure if the debbuger is precise, it tells me it’s the velocity line but for me the next line which is move_and_slide() should be more costly, doesn’t it ?
Likely it is just too costly to use CharacterBody move_and_slide() in your setup. You might need to use an actual debug build of Godot and look at a debugger to get a real full picture. Some of the usual culprits were already mentioned.
The line “velocity = safe_velocity” just sets the velocity property on the node. That has no real performance effect on anything even in the core code.
You might have looked at just the script debugger that can only track things that you do in your script. It does not give you a full picture of what is going on with the actual engine functions. E.g. a script call to an engine function might display cheap in a script debugger because the script call isolated is cheap when it just adds a command in a queue. That the call triggers a lot of heavy lifting functions executed later in sync phases of servers done by the engine is not part of a script debugger performance and might just show up as a big process() or physics_process() performance bottleneck in the debug monitors.
Oh I understand better now. So it may be just move_and_slide()? But this method is really useful and it’s what I want it looks like, people “sliding” on things. But maybe it can’t be more optimized if I want that “sliding” behavior. Or I thinked about using it only when collision/obstacle is detected, and switch from kinematic to physics when needed, but I can’t switch the node type like that. Because move_and_slide() is only available on CharacterBody3D, not Node3D nor Rigidbody3D.
For debug build, I have no clue how to do. Where are the guides? Is it a new godot executable or is it an add-on/plugin?
Engine development documentation that you find here Engine development — Godot Engine (latest) documentation in English. You need to use a Godot build with debug symbols and pick one of the many debuggers available for whatever OS you are using. The documentation has a few options listed.
Either build the engine from source yourself with debug symbols or you can grab build artifacs form various sources, e.g. here are some for the most recent master versions of Godot here Godot Commit Artifacts