How to Synchronize Ragdolls with using GodotSteam

Godot Version

4.2.2 steam-audio fork

Question

First of all, I want to tell you what I expect. The ragdoll’s arms and legs can be in different positions, but as long as they are in the same position at the root.

To synchronize, I took the global positions and rotations of all the bones and sent them to the other players. It actually works, but it’s really bad.

Now you can say just take the bone at the root and send its position and rotation, but this makes the mesh bad.

Actually, my goal is to synchronize only the root bone without breaking the simulation.

@icon("res://Network/RadomeSteamSync/SyncNode/transformSyncIcon.png")
extends Node

@export_group("SETTINGS","is")
@export var is_only_lobby_owner : bool = false ## Sadece Lobby Owner Gonderecek

@export_group("NODES","object")
@export var object_player : Node ## Karakteri sec eger lobby owner yollayacaksa gerek yok

var bones : Array[PhysicalBone3D]

signal simulating(status : bool)

var packet_index_pos : int = 0
var packet_index_rot : int = 0


var last_pos : Array[Vector3]
var last_rot : Array[Vector3]


var transform_buffer : Array = [null,null]
var last_index_buffer : PackedInt32Array = [0,0]



func _ready():
	get_all_bones()
func get_pos_bone() -> Array[Vector3]:
	var pos : Array[Vector3]
	for bone in bones:
		pos.append(bone.global_position)
 
	return pos
	
func get_rot_bone() -> Array[Vector3]:
	var rot : Array[Vector3]
	for bone in bones:
		rot.append(bone.rotation)
	return rot

func get_all_bones():
	for i in get_parent().get_children():
		if is_instance_of(i,PhysicalBone3D):
			bones.append(i)
func _on_pos_timer_timeout():

	if get_pos_bone() != last_pos and NetworkManager.GAME_STARTED:
		var pos = get_pos_bone()
		var DATA : Dictionary = {"Idx":packet_index_pos + 1,"TYPE":NetworkManager.TYPES.RAGDOLL,"value":pos,"node_path":get_path(),"property":"pos"}	
		P2P._send_P2P_Packet(0,0, DATA,Steam.P2P_SEND_UNRELIABLE)
		packet_index_pos = packet_index_pos + 1
		last_pos = pos


func _on_rot_timer_timeout():

	if get_rot_bone() != last_rot and NetworkManager.GAME_STARTED:
		var rot = get_rot_bone()
		var DATA : Dictionary = {"Idx":packet_index_rot + 1,"TYPE":NetworkManager.TYPES.RAGDOLL,"value":rot,"node_path":get_path(),"property":"rot"}	
		P2P._send_P2P_Packet(0,0, DATA,Steam.P2P_SEND_UNRELIABLE)
		packet_index_rot = packet_index_rot + 1
		last_rot = rot


func _physics_process(delta):
	if transform_buffer[0] != null and NetworkManager.GAME_STARTED:
		if transform_buffer[0]["Idx"] >= last_index_buffer[0] :
			set_pos_bone(transform_buffer[0]["value"]) 
	# Rotation
	if transform_buffer[1] != null and NetworkManager.GAME_STARTED:
		if transform_buffer[1]["Idx"] >= last_index_buffer[1]:
			set_rot_bone(transform_buffer[1]["value"])

func set_pos_bone(DATA):
	for i in range(bones.size()):
		var lerped_value = lerp(bones[i].global_position,DATA[i],0.35)
		bones[i].global_position = lerped_value
		last_index_buffer[1] = transform_buffer[1]["Idx"]

func set_rot_bone(DATA):
	for i in range(bones.size()):
		var lerped_value = lerp(bones[i].rotation,DATA[i],0.35)
		bones[i].rotation = lerped_value
		last_index_buffer[1] = transform_buffer[1]["Idx"]

		
func abort():
	set_process(false)
	$PosTimer.stop()
	$RotTimer.stop()

func _on_simulating(status : bool):
	if status== true:
		if is_only_lobby_owner and Steam.getLobbyOwner(NetworkManager.LOBBY_ID) == NetworkManager.STEAM_ID:
			$PosTimer.start()
			$RotTimer.start()
		elif !is_only_lobby_owner and str(NetworkManager.STEAM_ID) == object_player.name:
			$PosTimer.start()
			$RotTimer.start()
			print("simulated")
	else:
		$PosTimer.stop()
		$RotTimer.stop()


Also i tried with set_bone_global_pose_override() but this made it much worse.

As usual, I solved the question I opened myself in the forum :slight_smile: . I’m not sure how I solved the problem :smiley: but it could be one of several reasons. When solving the problem I used global_transform.origin as position value, and global_transform.basis.get_rotation_quaternion() as rotation value.
image


I think you see the problem I am trying to return the quaternion value as Vector3. But I didn’t notice this at first and tried to run the game like this and the ragdoll synchronization in the game improved and works without any problems. But later I looked and there were 46000 errors in the Debug section. Anyway, then I set it to Quaternion instead of Vector3. When I tried it again, the ragdoll was very bad. I realized that it was the rotation value, so I deleted them all and it’s working fine now. But right now I’m not sure if it didn’t work because of global_position or rotation.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.