add client prediction

This commit is contained in:
2025-02-19 22:23:06 +09:00
parent 4e65d2c43b
commit ac49bcee0b
9 changed files with 34 additions and 19 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ config_version=5
config/name="Instructions Clear" config/name="Instructions Clear"
run/main_scene="res://scenes/empty.tscn" run/main_scene="res://scenes/empty.tscn"
config/features=PackedStringArray("4.3", "Mobile") config/features=PackedStringArray("4.3", "Mobile")
run/max_fps=240 run/max_fps=120
boot_splash/show_image=false boot_splash/show_image=false
config/icon="res://icon.svg" config/icon="res://icon.svg"
run/size/borderless=false run/size/borderless=false
-2
View File
@@ -143,14 +143,12 @@ mesh = SubResource("BoxMesh_lm401")
[node name="FirstFloorLight" type="OmniLight3D" parent="Lights"] [node name="FirstFloorLight" type="OmniLight3D" parent="Lights"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0)
light_energy = 6.0
shadow_enabled = true shadow_enabled = true
omni_range = 40.0 omni_range = 40.0
omni_attenuation = 1.5 omni_attenuation = 1.5
[node name="SecondFloorLight" type="OmniLight3D" parent="Lights"] [node name="SecondFloorLight" type="OmniLight3D" parent="Lights"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9, 0)
light_energy = 6.0
shadow_enabled = true shadow_enabled = true
omni_range = 40.0 omni_range = 40.0
omni_attenuation = 1.5 omni_attenuation = 1.5
+2
View File
@@ -116,3 +116,5 @@ script = ExtResource("7_jfat4")
[node name="Walk" type="Node" parent="StateMachine"] [node name="Walk" type="Node" parent="StateMachine"]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("8_phh70") script = ExtResource("8_phh70")
[connection signal="delta_synchronized" from="Sync" to="." method="_on_sync_delta_synchronized"]
+20 -5
View File
@@ -19,10 +19,16 @@ extends CharacterBody3D
@export var air_deceleration := 5.0 @export var air_deceleration := 5.0
@export var rotation_speed := 20.0 @export var rotation_speed := 20.0
@export_group("Client Tweening") @export_group("Client Smoothing")
@export var client_smoothing := false @export var client_smoothing := false
@export var client_smoothing_speed := 10.0 @export var client_smoothing_speed := 10.0
@export var client_smoothing_rotation_speed := 25.0 @export var client_smoothing_rotation_speed := 25.0
@export var client_prediction := false
@export var client_prediction_tolerance := 0.3
@export_group("Server variables")
@export var server_position := Vector3.ZERO
@export var server_rotation := Vector3.ZERO
@onready var _camera_pivot: Node3D = %CameraPivot @onready var _camera_pivot: Node3D = %CameraPivot
@onready var _camera_platform: Node3D = %CameraPlatform @onready var _camera_platform: Node3D = %CameraPlatform
@@ -32,9 +38,8 @@ extends CharacterBody3D
var camera_input_direction := Vector2.ZERO var camera_input_direction := Vector2.ZERO
var last_direction := Vector3.FORWARD var last_direction := Vector3.FORWARD
@export_group("Server variables") var predicted_position := Vector3.ZERO
@export var server_position := Vector3.ZERO var predicted_rotation := Vector3.ZERO
@export var server_rotation := Vector3.ZERO
func _ready() -> void: func _ready() -> void:
state_machine.set_subject(self) state_machine.set_subject(self)
@@ -80,6 +85,11 @@ func _physics_process(delta: float) -> void:
camera_input_direction = Vector2.ZERO camera_input_direction = Vector2.ZERO
if not multiplayer.is_server(): if not multiplayer.is_server():
if multiplayer.get_unique_id() == player_id and client_prediction:
predicted_position = position
predicted_rotation = skin.global_rotation
if multiplayer.get_unique_id() != player_id or not client_prediction:
if client_smoothing: if client_smoothing:
position = lerp(position, server_position, client_smoothing_speed * delta) position = lerp(position, server_position, client_smoothing_speed * delta)
skin.global_rotation.y = lerp_angle(skin.global_rotation.y, server_rotation.y, client_smoothing_rotation_speed * delta) skin.global_rotation.y = lerp_angle(skin.global_rotation.y, server_rotation.y, client_smoothing_rotation_speed * delta)
@@ -90,4 +100,9 @@ func _physics_process(delta: float) -> void:
if multiplayer.is_server(): if multiplayer.is_server():
server_position = position server_position = position
server_rotation = skin.global_rotation server_rotation = skin.global_rotation
#print("Velocity: %s" % velocity) pass
func _on_sync_delta_synchronized() -> void:
if client_prediction and server_position.distance_to(predicted_position) > client_prediction_tolerance:
print("%v VS %v" % [server_position, predicted_position])
position = server_position
+1 -1
View File
@@ -1,7 +1,7 @@
extends State extends State
func process_physics(delta: float) -> State: func process_physics(delta: float) -> State:
if not multiplayer.is_server(): if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction):
return return
var target_velocity = Vector3(0, subject.velocity.y, 0) var target_velocity = Vector3(0, subject.velocity.y, 0)
+1 -1
View File
@@ -1,7 +1,7 @@
extends State extends State
func process_physics(delta: float) -> State: func process_physics(delta: float) -> State:
if not multiplayer.is_server(): if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction):
return return
var target_velocity = Vector3(0, subject.velocity.y, 0) var target_velocity = Vector3(0, subject.velocity.y, 0)
+1 -1
View File
@@ -1,7 +1,7 @@
extends State extends State
func process_physics(delta: float) -> State: func process_physics(delta: float) -> State:
if not multiplayer.is_server(): if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction):
return return
var input_direction = %Input.direction var input_direction = %Input.direction
+1 -1
View File
@@ -14,7 +14,7 @@ func _change_state(new_state: State) -> void:
current_state.exit() current_state.exit()
current_state = new_state current_state = new_state
print("Entering: %s" % current_state.name) #print("Entering: %s" % current_state.name)
current_state.enter() current_state.enter()
func process_physics(delta: float) -> void: func process_physics(delta: float) -> void:
+1 -1
View File
@@ -1,7 +1,7 @@
extends State extends State
func process_physics(delta: float) -> State: func process_physics(delta: float) -> State:
if not multiplayer.is_server(): if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction):
return return
var input_direction = %Input.direction var input_direction = %Input.direction