Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RopeInteraction node overstretching. #16

Closed
ProbablyIdiot opened this issue Aug 1, 2024 · 7 comments
Closed

RopeInteraction node overstretching. #16

ProbablyIdiot opened this issue Aug 1, 2024 · 7 comments

Comments

@ProbablyIdiot
Copy link

Hello,
This leads on from the previous issue (#10 ), I followed your advice, updated to 1.3 and used the RopeInteraction node on 2 CharacterBody2Ds. However, if one of the players jumps off of the platform, they are not limited by the rope. I understand that this may not be a bug, so - if it isn't - how can I limit the distance between them. Video attached to explasin was too large, so I zipped it:
RopeBound (DEBUG) 2024-08-01 19-46-36.zip

@mphe
Copy link
Owner

mphe commented Aug 1, 2024

See also the rope_pulling example.
You need to set the strength on the RopeInteraction to 1.0.
Also set Rope.max_endpoint_distance to the desired maximum stretched rope length.

@ProbablyIdiot
Copy link
Author

@mphe Sorry I only just saw this, they were already set with those settings.

@mphe
Copy link
Owner

mphe commented Aug 6, 2024

Could you upload a minimal reproduction project?

@ProbablyIdiot
Copy link
Author

https://drive.google.com/file/d/1O7AIIKTFIekjGFVu8Pni12vls6Yns4Mv/view?usp=sharing
It's too big for github, so here's a gdrive link. Make sure you have visibile collision shapes turned on, as there aren't any sprites.

@mphe
Copy link
Owner

mphe commented Aug 6, 2024

If it's too large for Github, it's not minimal :)
An MRP only contains the minimum necessary content to demonstrate the problem. In this case you should remove all the plugins except ropesim. You should also remove the .git folder which alone has 20MB.

Anyway, I think I know what the problem is and it is indeed a ropesim bug.
It seems to be an execution order problem. Rope simulation takes place at the beginning of the physics frame. The scripts on the player nodes are executed afterwards. That means the rope is simulated, then the CharacterBodies are constrained, then the CharacterBodies move, which results in the CharacterBodies being slightly off the computed rope position.
Since the y velocity continuously increases due to gravity, the position difference will become larger and larger.
The rope itself is constrained correctly.

I will try to look into it over the weekend.
Until then, you can try to workaround it by not applying gravity when the vertical distance to the other player node exceeds the rope length and the vertical velocity goes downwards.

Like this:

extends CharacterBody2D

@onready var PLAYER = $"."
@onready var SPRITE = $"Sprite2D"
@onready var ANIM = $AnimationPlayer

@export var vertSpeed = -750
@export var speed = 400
@export var gravity = 2500
@export var other_player: Node2D   # NEW

var onfloor = false
var jumptimes = 1


func _physics_process(delta):
	# Is CharacterBody on floor:
	if is_on_floor():
		onfloor = true
		jumptimes = 0
	else:
		onfloor = false

        # NEW
	if not is_on_floor() and not (abs(other_player.global_position.y - global_position.y) > 200 and velocity.y > 0):
		velocity.y += gravity * delta

	velocity.x = Input.get_axis("blue-left", "blue-right") * speed

	if Input.is_action_just_pressed("blue-up") and jumptimes <= 1:
		jumptimes += 1
		velocity.y = vertSpeed

	move_and_slide()

@mphe
Copy link
Owner

mphe commented Aug 18, 2024

I investigated some more and did some experimenting.

There is actually another problem in addition to what I already mentioned.
When the rope max length is exceeded, both endpoints are contracted together to their center.
Now, if one player is standing on the platform and the other is hanging and pulling the rope downwards, the rope will be stretched and contracted towards the center between both endpoints, causing a gap between the players and the rope. Afterwards the character bodies are moved to the respective points on the rope, which should close the gap. For the hanging body this is no problem, but the other body stands on the platform and cannot move through it, hence the gap there will perstist. This gap is also getting larger as the gravity on the other player increases.

This is a problem that cannot be solved easily.
I just pushed a commit that allows to specify in which direction the rope should be contracted when the max length is exceeded using the new properties resolve_to_begin and resolve_to_end.
You can get the new build here.

A workaround I found was to dynamically set these properties to true when the respective player is on ground and to false when not.
So blue player sets resolve_to_begin and yellow player sets resolve_to_end. This ensures that the rope will be contracted towards the player who stands on the ground. If both are on ground, i.e. when both flags are set, the rope will be contracted towards the center as before.
So if one player is hanging, the rope is guaranteed to be contracted towards the other player, so that no gap can appear.

To solve the problem I mentioned in my last reply, you need to run the player _physics_process code before ropes get updated.
To do this, you need to connect to the NativeRopeServer.on_pre_update signal and run your physics code there instead of in _physics_process.

These measurements should prevent overstretching.
As it is getting a little complicated, here is an adapted version of your example project: Rope stretch example.zip

Another alternative solution to the resolve_to_xy approach: you can try to set the strength property on the respective RopeInteraction of a player to 1.0 when on ground and to 0.0 when not. There needs to be a certain threshold though. If you set it immediately, it will likely cause unexpected behavior. You can try something like if y > other_player.y and not on_floor: strength = 0.0 else: strength = 1.0.
Using strength 0.0 gives the rope more control to constrain itself, which should prevent overstretching and also enables better swinging for the hanging player.
But I haven't tested it, so don't know how well it works in your case.

There is still one thing that you need to address: the vertical velocity of the hanging player will still gradually increase without limit, which will cause further problems.
For example, when the player on the platform jumps, it will jitter a lot. This happens because whenever the player moves a few pixels up, it gets pulled down immediately by the other player.
So you will need some logic to handle this properly.

@ProbablyIdiot
Copy link
Author

ProbablyIdiot commented Sep 23, 2024

@mphe I'm so sorry, I realised I forgot to thank you and close this issue! Your solution works a treat, thanks for all your hard work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants