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

[godot] no support for world position/rotation physics #2573

Open
yoont4 opened this issue Jul 8, 2024 · 4 comments
Open

[godot] no support for world position/rotation physics #2573

yoont4 opened this issue Jul 8, 2024 · 4 comments
Assignees

Comments

@yoont4
Copy link

yoont4 commented Jul 8, 2024

As the title describes, setting the position/rotation of a SpineSprite doesn't cause any of the physics constraints to do anything. You have to do some direct transform modification which is very clunky and error prone:

var cog = get_skeleton().find_bone("cog")
var current_transform = cog.get_global_transform()
var pos_delta = (target_bone_position + bone_offset) - current_transform.get_origin()
var new_transform = current_transform.translated(pos_delta)
cog.set_global_transform(new_transform)

Whereas I'd much rather have it respond to physics changes from typical sprite-level interactions:

# Ideally it would respond to sprite/node-level changes
global_position = target_position
rotation = target_rotation

Would it be possible to have a toggle if necessary to enable world-space physics calculation, rather than requiring direct modification to the internal skeleton positions?

@yoont4
Copy link
Author

yoont4 commented Jul 8, 2024

Also unrelated question, but would like some clarification before I open a separate ticket. Does the Spine runtime calculate physics on its own tick-rate? Because it looks perfect on a locked 60FPS project, but if I uncap it and run at 144FPS, even if I raise the godot physics tick rate to match, I still get that classic jittering that usually comes from differing tick-rates.

@badlogic
Copy link
Collaborator

badlogic commented Jul 9, 2024

To answer your second question, you can configure when SpineSprite ticks:
https://esotericsoftware.com/spine-godot#Setting-the-Update-Mode

Regarding physics constraints, SpineSkeleton has two methods:

  • physics_translate(x, y): lets you apply translational displacement to the physics constraints
  • physics_rotate(x, y, degrees): lets you apply rotational displacement to physics constraints

At the moment, you have to call those manually. I have to see if I can wire up global_position on SpineSprite to (optionally, via a flag) call physics_translate() internally.

@badlogic badlogic self-assigned this Jul 9, 2024
@yoont4
Copy link
Author

yoont4 commented Jul 10, 2024

Thanks for the reply, I did not know about physics_translate/rotate, those are very useful to know!

Unfortunately the update mode flag doesn't really effect it. I've tried every setting, including manual and calling it on each _process() call.

I've found an additional detail that helps repro it easily though. It seems that for any FPS above or below 60, there is a weird "jolt" that happens every 1/X seconds. So at 61FPS, it jolts every ~1 second, at 62FPS every ~0.5 seconds, and so on. Which makes sense why uncapped at 144FPS (my monitor refresh rate), it seems to jitter every frame.

It's very easy to visualize by calling physics_rotate(0, 0, 10) on a simple 2-bone physics constraint:

61 FPS:

61_fps.mp4

62 FPS:

62_fps.mp4

70 FPS:

70_fps.mp4

At 60FPS, there's no jittering. This makes me think that the internal physics update logic is somehow desynced with the actual sprite mesh updating, since normal animations stay smooth regardless of FPS on process update mode.

NOTE: I am only applying the physics rotation to the skeleton so that it's easier to see. It still happens if I rotate the SpineSprite with it like I would in practice.

@badlogic
Copy link
Collaborator

badlogic commented Oct 2, 2024

Sorry, I just found time to get back to this. @yoont4 could you share the scene script and assets?

All timing related code is contained here:
https://github.com/EsotericSoftware/spine-runtimes/blob/4.2/spine-godot/spine_godot/SpineSprite.cpp#L676

This method receivces it's delta time either by manually calling SpineSprite::update_skeleton(), or in SpineSprite::_notification(), which passes either the process delta time, or the physics process delta time, depending on the update mode.

There's nothing anywhere in the code that would make things only work at 60fps, so I'm a bit puzzled. I also can't reproduce the issue using the celeste example on a 120Hz screen.

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

No branches or pull requests

2 participants