Epicycle rotation and possible engine bug

For the challenge I’ve written a scene that traces out an epicycle using a Line2D spawning points every frame from the fifth child. However, the root node sometimes moves over one frame, even though I didn’t tell it to do that. Have I found an engine bug or is it something else?

The root node seen after it moves:

It seems to generally move down, and only by a lot over one frame.

My scripts. The Line2D is a child of the last UFO:

extends RigidBody2D

@export var rotation_speed: float = 2.2

func _process(delta):
	rotation += delta*rotation_speed;
extends Line2D

func _process(_delta):
	add_point(get_parent().global_position)
	transform = get_parent().global_transform.inverse()
	if get_point_count() > 1000:
		remove_point(0)
1 Like

Hm. That’s a neat idea. I think a video or gif would give people a better understanding of what you’re doing here - epicycles are pretty interesting to watch, and I imagine most people don’t know the term (I certainly didn’t!)

Regarding the moving root node, what have you tried so far to simplify the system and isolate the problem area? Does essentially the same thing happen using just 2 saucers and the root node for example?

Also, what exactly is your root in this scene? Is it a level (more or less), a saucer, an ordinary Node2D, or something else?

No problem, here’s a gif. Unfortunately the forum won’t allow the full webm…

Screencast from 04-29-2024 01_37_25 PM (1)

My root node is a Node2D, then there’s the TextureRect background and the hierarchy of Player instanced scenes, which all have a RigidBody2D at their root. At the bottom of that hierarchy is the Line2D with its attached script. I’m guessing it’s a bad interaction between the physics engine and changing the rotation of the Players. I was able to make the issue much worse by setting gravity scale on all of the nodes to 0, whereas I’d set some of them to 2. In this case it seems that all of the nodes drift apart jankily over time.

Here’s the tscn that you see running in the most recent screenshot.

[gd_scene load_steps=5 format=3 uid="uid://cr7ufpgcuaxkd"]

[ext_resource type="Texture2D" uid="uid://cmxaxyjsbwipx" path="res://speedy_saucer_assets/purple.png" id="1_lvov1"]
[ext_resource type="PackedScene" uid="uid://shhrqtpe78do" path="res://player.tscn" id="2_48lj8"]
[ext_resource type="Script" path="res://trail.gd" id="3_ulo8q"]

[sub_resource type="Gradient" id="Gradient_v31xw"]
colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1)

[node name="Level1" type="Node2D"]

[node name="background" type="TextureRect" parent="."]
z_index = -1
texture_repeat = 2
offset_left = -42.0
offset_top = -51.0
offset_right = 1214.0
offset_bottom = 723.0
texture = ExtResource("1_lvov1")
stretch_mode = 1

[node name="player" parent="." instance=ExtResource("2_48lj8")]
position = Vector2(631, 190)

[node name="player2" parent="player" instance=ExtResource("2_48lj8")]
position = Vector2(-94, -6)
rotation_speed = 2.635

[node name="player3" parent="player/player2" instance=ExtResource("2_48lj8")]
position = Vector2(-97, 6)

[node name="player4" parent="player/player2/player3" instance=ExtResource("2_48lj8")]
position = Vector2(-94, 6)
rotation_speed = 1.66

[node name="player5" parent="player/player2/player3/player4" instance=ExtResource("2_48lj8")]
position = Vector2(47, 162)

[node name="Line2D" type="Line2D" parent="player/player2/player3/player4/player5"]
gradient = SubResource("Gradient_v31xw")
script = ExtResource("3_ulo8q")

I’m guessing the workaround here is to “move a rigidbody with impulses” instead of what I’m doing right now. I will try it after I get off work today.

Yes, this is what I thought you were doing. A fun thing to watch, especially with this tracer line on the end =)

More than likely this is why; as far as I can tell, you are mixing kinematic movement (setting rotation) with dynamic movement (internal physics calculations done on PhysicsBodies such as the RigidBody2D). In short, that’s asking for problems because the kinematic adjustments are not automatically factored in with the physics calculations, so you end up with conflicting final results that can cause rubber-banding and the like.

I had lots of problems with that when I extended this project after the course, and in the end I had to make the player sleep during kinematic adjustments. That won’t be practical in this case because it’s happening every frame, but I think it would work fine if you tried this with Sprite2Ds instead of the RigidBodies. Either way, very cool =)

1 Like

Privacy & Terms