Skip to content

Add solver_priority to Jolt constraint priority#119976

Open
almic wants to merge 1 commit into
godotengine:masterfrom
almic:add-jolt-constraint-priority
Open

Add solver_priority to Jolt constraint priority#119976
almic wants to merge 1 commit into
godotengine:masterfrom
almic:add-jolt-constraint-priority

Conversation

@almic
Copy link
Copy Markdown
Contributor

@almic almic commented Jun 2, 2026

  • Jolt does have solver priorities, now you can set them

What problem(s) does this PR solve?

  • I could not find any issues mentioning this

Additional information

Jolt has constraint priorities which fulfills the purpose of ordering joint constraints in the step process. Right now Godot prints an error and claims that solver_priority is not supported in Jolt, but it is!

Copy link
Copy Markdown
Contributor

@jrouwe jrouwe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that according to the documentation, Jolt's priority works opposite to Godot's priority. Godot:

Image

Vs Jolt:

/// Priority of the constraint when solving. Higher numbers are more likely to be solved correctly.

Looking at the code for GodotPhysics I think the tooltip doesn't describe what actually happens:

int current_priority = 1;
uint32_t constraint_count = constraint_island.size();
while (constraint_count > 0) {
for (int i = 0; i < iterations; i++) {
// Go through all iterations.
for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) {
constraint_island[constraint_index]->solve(delta);
}
}
// Check priority to keep only higher priority constraints.
uint32_t priority_constraint_count = 0;
++current_priority;
for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) {
GodotConstraint3D *constraint = constraint_island[constraint_index];
if (constraint->get_priority() >= current_priority) {
// Keep this constraint for the next iteration.
constraint_island[priority_constraint_count++] = constraint;
}
}
constraint_count = priority_constraint_count;
}

If I read this code then it will first call solve() iterations times on each constraint in the current island. Then it will loop and remove all constraints with priority 1. After that it will call solve() iterations times on the remaining constraints. Then it will loop and remove all constraints with priority 2. etc. This happens until there are no constraints left. So if you set the constraint priority to 1000, then that constraint will actually be solved 1000 * iterations times, which will be insanely slow. Note that the UI limits the max value to 8, but I think you can set it to any value if you script it. Waht this boils down to is that joints with higher priorities will be solved more accurately.

Jolt on the other hand uses the priority only to sort the constraints, so all constraints will be solved iterations times, but the highest priority joints are solved last which means that they will be solved more accurately (the first constraints can be violated when solving the last constraints).

I think the tool tip needs to be adjusted to:

  • Reflect that higher values have a higher priority.
  • Remove the note that Jolt doesn't support it.

As you can pass an int to the set_solver_priority function and it is cast to an unsigned integer, I think the value set should be max(0, value).

@almic
Copy link
Copy Markdown
Contributor Author

almic commented Jun 3, 2026

So if you set the constraint priority to 1000, then that constraint will actually be solved 1000 * iterations times, which will be insanely slow. Note that the UI limits the max value to 8, but I think you can set it to any value if you script it.
Jolt on the other hand uses the priority only to sort the constraints, so all constraints will be solved iterations times, but the highest priority joints are solved last which means that they will be solved more accurately (the first constraints can be violated when solving the last constraints).

Wow... so basically if someone assumes the sorting strategy (which is how the concept of "priority" should be handled), and increments their joints as they create them, switching to Godot physics would probably instantly crash any project with more than 10 constraints.

I think the tool tip needs to be adjusted to:

  • Reflect that higher values have a higher priority.
  • Remove the note that Jolt doesn't support it.

Yes, I agree. I forgot to update the documentation.

As you can pass an int to the set_solver_priority function and it is cast to an unsigned integer, I think the value set should be max(0, value).

Initially when I was using priorities, I had the idea to start at -1 and decrement a priority variable as I set up my joints. This basically has the intention of making joints created A, B, C run as C, B, A. I'm not sure of where compilers may differ, but it should probably be supported to use negative numbers as a strategy to say "maximum priority" minus 1, then minus 2, etc. Maybe this is crazy. Personally though, I like the option.

I saw that Jolt runs with uints, and I didn't confirm it, but I was running with "negative" priorities assuming the cast will underflow. It probably wasn't though. Whatever way, the doc should mention what happens with negative values, as normal ints in GDScript are always signed.

@almic almic force-pushed the add-jolt-constraint-priority branch from 2209ce8 to 3f71b7d Compare June 3, 2026 15:38
@almic almic requested a review from a team as a code owner June 3, 2026 15:38
Comment thread modules/godot_physics_3d/godot_constraint_3d.h Outdated
Comment thread modules/jolt_physics/joints/jolt_joint_3d.cpp Outdated
- Jolt does have solver priorities, now you can set them
@almic almic force-pushed the add-jolt-constraint-priority branch from 3f71b7d to c52897b Compare June 3, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants