Skip to content

Commit 714a635

Browse files
committed
Update documentation
1 parent fbf65fe commit 714a635

4 files changed

Lines changed: 129 additions & 0 deletions

File tree

FAQ.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# FAQ / Troubleshooting
2+
3+
## Is Web export supported?
4+
5+
Yes, partially.
6+
The plugin includes a web build, but since it uses GDExtension, a web export template with GDExtension support is required to use it.
7+
8+
According to the [Godot documentation](https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_for_web.html#gdextension) for web:
9+
> "The default export templates do not include GDExtension support for performance and compatibility reasons".
10+
11+
That means in order to use the web version of this plugin, you will need a custom web export template compiled with `dlink_enabled=yes`.
12+
13+
To compile it yourself, refer to the official Godot documentation for further information: [Building from source](https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html), [Compiling for the Web](https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_for_web.html) and [Exporting for the Web](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_web.html).
14+
15+
Alternatively, you can download prebuilt export templates from another trusted source.
16+
For example, the [LimboAI addon](https://github.com/limbonaut/limboai) provides web export templates with GDExtension support.
17+
18+
## Ropes lag one frame behind
19+
20+
This is a known issue and related to execution order.
21+
22+
**TL;DR:** Connect to the `NativeRopeServer.on_pre_pre_update` signal and run the rope update code there. It is essentially an alternative to `_physics_process()` that runs just before ropes get updated.
23+
24+
See [Execution Order Documentation](docs/execution_order.md) for a more detailed explanation.
25+
26+
27+
## Collisions tunnel through objects / stretch along corners
28+
29+
See [Collisions Documentation](docs/collisions.md).

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ When one of the above nodes is selected, a "*Ropesim*" menu appears in the edito
6767
* `Preview in Editor`: Toggle live preview in the editor on or off.
6868
* `Reset Rope`: Reset the selected rope to its resting position.
6969

70+
### Advanced Topics
71+
- [Collisions Documentation](docs/collisions.md)
72+
- [Execution Order Documentation](docs/execution_order.md)
73+
74+
75+
## FAQ / Troubleshooting
76+
77+
See [FAQ](FAQ.md).
78+
79+
7080
## Showcase
7181

7282
A quick overview of how to use each node.

docs/collisions.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Collisions
2+
3+
## Overview
4+
5+
At each rope point a circle collision check will be performed. If there is a collision, the rope point will be moved to a safe space.
6+
This can cause the tunneling and stretching since only discrete areas are checked for collisions, not whole rope segments.
7+
Usually, with relatively smooth topology, the circle colliders nicely slide along it, but with sharp corners, it will be very difficult to prevent stretching, because they effectively pierce between the colliders and separate them.
8+
9+
## Why Not Check Whole Segments?
10+
11+
Resolving collisions with whole rope segments would involve much more complex logic with respectively larger computation times.
12+
That kinda defeats the purpose of this plugin.
13+
The current implementation is simple, fast and good enough for most use-cases.
14+
If perfect precision is needed, it's probably better to build a rope out of rigidbodies using built-in physics.
15+
16+
## Tweaking Collisions
17+
18+
The following properties can be tweaked to improve collision response:
19+
20+
- `num_segments`
21+
- `num_constraint_iterations`
22+
- `collision_radius`
23+
- `resolve_collisions_while_constraining`
24+
25+
Also very helpful is `render_debug` as it will display the effective collider areas as cyan circles.
26+
It helps visualizing how much space is covered by colliders and the effect of tuning the above properties (except the last one).
27+
28+
Increasing `num_segments` also increases the amount of collision tests, which results in more precise collision detection.
29+
I found 10 segments per 100 pixel length a good value, but it very much depends on the use case.
30+
31+
Increasing `num_segments` will very likely also require increasing `num_constraint_iterations` as well to hold the rope together properly.
32+
For `num_constraint_iterations` there is no rule of thumb. The less iterations, the stretchier the rope will become.
33+
More iterations make the rope tighter and less bouncy/stretchy, but it will also increase computation time respectively.
34+
More segments require more constraint iterations to keep the rope equally tight.
35+
When increasing constraint iterations the rope's length becomes closer to `rope_length` and the colliders move closer together, reducing the gap between them.
36+
37+
`collision_radius` is the radius of the colliders. Larger colliders cover more space and thus reduce tunneling/stretching. It can't solve it completely, though.
38+
There is also no rule of thumb, you have to play around with it until you find a sweet spot.
39+
40+
Finally, `resolve_collisions_while_constraining` helps a lot to reduce tunneling/stretching by running the collision test after every single constraint iteration instead of once after the constraint step finished.
41+
Consequently, it also drastically affects the computation time in relation to `num_constraint_iterations`.
42+
With only a few ropes, it's fine, but with many ropes it can tank the framerate.
43+
44+
As for balancing computation cost, keep an eye on `NativeRopeServer.get_computation_time()`.
45+
There is a script `rope_examples/scripts/PerformanceLabel.gd` that can be used.

docs/execution_order.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Execution Order
2+
3+
Ropes are not processed by their node but in the `NativeRopeServer` class, which executes at the start of the physics frame, i.e. when the `SceneTree.physics_frame` signal runs.
4+
5+
Roughly sketched, the order looks like this:
6+
7+
1. `SceneTree.physics_frame`
8+
- Rope update
9+
2. `_process()`
10+
3. `_physics_process()`
11+
12+
This assumes that the FPS match the physics tickrate, which is usually locked at 60 FPS.
13+
On a 144 Hz screen for example, it wouldn't match and you get more `_process()` frames than `_physics_process()` possibly making this lag even more noticable.
14+
15+
`NativeRopeServer` provides a set of signals for fine-tuned execution order handling:
16+
17+
- `on_pre_update`
18+
- `on_pre_pre_update`
19+
- `on_post_update`
20+
- `on_post_post_update.`
21+
22+
They get emitted just before/after rope updates.
23+
24+
1. `SceneTree.physics_frame`
25+
1. `on_pre_pre_update`
26+
2. `on_pre_update`
27+
3. Rope update
28+
4. `on_post_update`
29+
5. `on_post_post_update`
30+
2. `_process()`
31+
3. `_physics_process()`
32+
33+
These signals are also used by various rope utilities like `RopeAnchor`, `RopeHandle` or `RopeRendererLine2D` to update the rope's properties or their own just before/after rope updates occur.
34+
At the moment they use the normal `pre` and `post` signals, not `pre_pre` or `post_post`.
35+
36+
## Solving the One-Frame Delay
37+
38+
Updating the rope position in `_process()` or `_physics_process()` causes a one-frame delay because they run after the rope has already been updated.
39+
Hence, the result is only visible in the next frame.
40+
41+
The workaround is to connect to `NativeRopeServer.on_pre_pre_update` and update the rope's position there.
42+
It can essentially be treated as a kind of `_physics_process()` which runs just before rope updates.
43+
44+
You can take a look at the `rope_pulling.tscn` example.
45+
The player node there uses the same approach.

0 commit comments

Comments
 (0)