godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.9k stars 20.16k forks source link

Single bad frame with AnimationPlayer + PathFollow2D + callback_mode_process=physics #95416

Open dreiss opened 1 month ago

dreiss commented 1 month ago

Tested versions

Reproduces in 4.2.2 and 4.3 RC3

System information

Fedora Linux, Intel GPU, Compatibility renderer

Issue description

I put a Sprite2D inside a PathFollow2D being driven by an AnimationPlayer. The animation is supposed to "stand still" for 1.5 seconds, then drive the sprite along the path in 0.5 seconds. The result is

https://github.com/user-attachments/assets/d223a65f-446f-4d3f-98f5-5c6898516317

The first frame as the sprite starts to move shows it "jumping" to the end. Then the animation continues as expected.

This only reproduces if the AnimationPlayer's callback_mode_process is physics. It is also sensitive to the time that the motion starts. If the keyframe is moved to 0.3 seconds, it no longer reproduces.

Steps to reproduce

Add this scene to a project and run it.

[gd_scene load_steps=6 format=3 uid="uid://so4a5fmgcrjy"]

[ext_resource type="Texture2D" uid="uid://bn446da160m5t" path="res://icon.svg" id="1_0hj8s"]

[sub_resource type="Curve2D" id="Curve2D_jck48"]
_data = {
"points": PackedVector2Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0)
}
point_count = 2

[sub_resource type="Animation" id="Animation_7d1jt"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Path2D/PathFollow2D:progress_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}

[sub_resource type="Animation" id="Animation_el4gs"]
resource_name = "walk"
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Path2D/PathFollow2D:progress_ratio")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.3, 1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, 0.0, 1.0]
}

[sub_resource type="AnimationLibrary" id="AnimationLibrary_mke75"]
_data = {
"RESET": SubResource("Animation_7d1jt"),
"walk": SubResource("Animation_el4gs")
}

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

[node name="Path2D" type="Path2D" parent="."]
curve = SubResource("Curve2D_jck48")

[node name="PathFollow2D" type="PathFollow2D" parent="Path2D"]

[node name="Sprite2D" type="Sprite2D" parent="Path2D/PathFollow2D"]
texture = ExtResource("1_0hj8s")

[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
callback_mode_process = 0
libraries = {
"": SubResource("AnimationLibrary_mke75")
}
autoplay = "walk"

Minimal reproduction project (MRP)

repro.zip

TokageItLab commented 1 month ago

This is a bug in the interpolation method of PathFollow rather than a bug in animation. 0 is treated as the end of the loop by the interpolation algorithm at the beginning of the interpolation between 0.3 and 1.0 because PathFollow is looping, although it is stationary at the 0 position between 0.0s and 0.3s. This is probably the cause of the problem.

image

For now, it is possible to work around this by either disabling loop or setting the values of the 0.0s and 0.3s keys to the miniscule value of 0.001.