What did i do bad?

Godot Version

4.5

Question

Why my multiplayer code doesn´t work? i just follow a tutorial, and my sonic stays in the air, while the code thinks it´s not the multiplayer authority. Someone can say to me what is bad with this code?
This is the Sonic code:

extends CharacterBody2D

#PUBLIC
var HP = 100

#PRIVATE
@export var animations: Node2D
var _cooldown_dropdash = 0
var _cooldown_peelout = 0
var _is_attacking = false
var _speed = 10
var _desacceleration = 20
var _speedmax = 300
var _speedmax_abilities = 450
var _jumpforce = -400
var _gravity = 15
var _coyote_time = 0.15
var _coyote_timer = 0.0
var _attack_dir = 1
var _abilitie_id = 0
var _abilitie_timer = 0
var _abilitie_time = 10.0
var _peelout_timer = 0
var _peelout_time = 5.0
var _jumping = false

func _enter_tree():
	set_multiplayer_authority(name.to_int())

func _physics_process(delta: float) -> void: #Movement
	if !is_multiplayer_authority(): return
	#X movement
	if _is_attacking == false:
		if Input.is_action_pressed("ui_left") or Input.is_action_pressed("ui_right"):
			if Input.is_action_pressed("ui_right"):
				velocity.x += _speed
				_attack_dir = 1
				if velocity.x > _speedmax:
					velocity.x = _speedmax
			if Input.is_action_pressed("ui_left"):
				velocity.x -= _speed
				_attack_dir = -1
				if velocity.x < -_speedmax:
					velocity.x = -_speedmax
		else:
			if velocity.x > 0:
				velocity.x -= _desacceleration
				if velocity.x < 0:
					velocity.x = 0
			if velocity.x < 0:
				velocity.x += _desacceleration
				if velocity.x > 0:
					velocity.x = 0
	else:
		if Input.is_action_pressed("ui_left") or Input.is_action_pressed("ui_right"):
			if Input.is_action_pressed("ui_right"):
				_attack_dir = 1
			if Input.is_action_pressed("ui_left"):
				_attack_dir = -1
	if _is_attacking == true:
		if _peelout_timer == 0:
			_abilitie_timer -= delta
			if _abilitie_timer < 0:
				_abilitie_timer = 0
				_is_attacking = false
				if _abilitie_id == 1:
					_cooldown_dropdash = 15.0
				if _abilitie_id == 2:
					_cooldown_peelout = 20.0
		if _abilitie_id == 2:
			if _peelout_timer > 0:
				_peelout_timer -= delta
			else:
				_peelout_timer = 0
			if _peelout_timer == 0:
				if _attack_dir == 1:
					velocity.x += _speed
					if velocity.x > _speedmax_abilities:
						velocity.x = _speedmax_abilities
					if _attack_dir == -1:
						velocity.x -= _speed
						if velocity.x < -_speedmax_abilities:
							velocity.x = -_speedmax_abilities
		elif _abilitie_id == 1:
			if _attack_dir == 1:
				velocity.x += _speed
				if velocity.x > _speedmax_abilities:
					velocity.x = _speedmax_abilities
			if _attack_dir == -1:
				velocity.x -= _speed
				if velocity.x < -_speedmax_abilities:
					velocity.x = -_speedmax_abilities
	if _cooldown_dropdash > 0:
		_cooldown_dropdash -= delta
		if _cooldown_dropdash < 0:
			_cooldown_dropdash = 0
	if _cooldown_peelout > 0:
		_cooldown_peelout -= delta
		if _cooldown_peelout < 0:
			_cooldown_peelout = 0
	#Y movement
	if !is_on_floor():
		velocity.y += _gravity
		_coyote_timer -= delta
	else:
		_coyote_timer = _coyote_time
		_jumping = false
	if Input.is_action_just_pressed("JumpKey") and _coyote_timer > 0:
		velocity.y = _jumpforce
		_coyote_timer = 0
		_jumping = true
	if is_on_floor():
		if Input.is_action_just_pressed("JumpKey"):
			velocity.y = _jumpforce
			_coyote_timer = 0
			_jumping = true
	move_and_slide()

func _process(delta): #Visuals
	if !is_multiplayer_authority(): return
	# Timer
	get_node("CanvasLayer/DropTimer").text = str(round(_cooldown_dropdash))
	get_node("CanvasLayer/PeelTimer").text = str(round(_cooldown_peelout))
	delta = delta
	if _is_attacking == true:
		if _abilitie_id == 1:
			if !is_on_floor():
				animations.play("dropdash")
			else:
				animations.play("ball")
		elif _abilitie_id == 2:
			if _peelout_timer < 4:
				animations.play("run")
			else:
				animations.play("walk")
	else:
		if _jumping == true: 
			animations.play("ball")
		else:
			if abs(velocity.x) > 250:
				animations.play("run")
			elif abs(velocity.x) > 5:
				animations.play("walk")
			else:
				animations.play("idle")
	if velocity.x > 0:
		animations.flip_h = false
	if velocity.x < 0:
		animations.flip_h = true

func _input(event): #AbilitiesKeys
	if !is_multiplayer_authority(): return
	if event is InputEventKey and event.pressed:
		if event.keycode == KEY_X and _cooldown_dropdash == 0 and _is_attacking == false:
			_is_attacking = true
			velocity.y = _jumpforce
			_jumping = true
			_abilitie_id = 1
			_abilitie_timer = _abilitie_time
		if event.keycode == KEY_C and _cooldown_peelout == 0 and _is_attacking == false:
			_is_attacking = true
			velocity.x = 0
			_peelout_timer = _peelout_time
			_abilitie_id = 2
			_abilitie_timer = _abilitie_time

this one is the multiplayer menu:

extends Node

@export var host_button: Button
@export var join_button: Button
@export var hud: Node
var peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new()

func _ready():
	host_button.pressed.connect(_on_host_pressed)
	join_button.pressed.connect(_on_join_pressed)

func _on_host_pressed():
	peer.create_server(3500, 2)
	multiplayer.multiplayer_peer = peer
	multiplayer.peer_connected.connect(_on_peer_connected)
	_on_peer_connected()
	hud.hide()

func _on_join_pressed():
	peer.create_client("localhost", 3500)
	multiplayer.multiplayer_peer = peer
	hud.hide()

func _on_peer_connected(id: int = 1):
	var player_scene = load("res://Scenes/Sonic.tscn")
	var player_instance = player_scene.instantiate()
	player_instance.name = str(id)
	print(id)
	add_child(player_instance, true)
	var level_scene = load("res://Scenes/TestLevel.tscn")
	var level_instance = level_scene.instantiate()
	add_child(level_instance, true)

Also, i have all the nodes i need, like the MultiplayerSynchronizer, and the MultiplayerSpawner, all with his things

edit:
i justo upgrated to godot 4.7 and noting changes :V
pls someone help me

We don’t know what tutorial you followed.

What have you tried to fix the issue? Whatever tutorial it is, the code looks extremely unreadable.

I highly doubt many people would want to help without even knowing what tutorial you tried to follow.

Also copy and paste any errors or messages that you are getting

I dont have any errors, thats the problem

You have 2 variables coyote_time and coyote_timer. My guess would be one of them is spelt wrong and should be the other variable.

No, the coyote_timer is the timer in air a d coyote_time is the time. I also said before the sonic works, has the gravity, moevemnt and all of that

The tutorial is in spanish, its this one: https://youtu.be/8fzmR70pn2E?si=JLIAM6XmnliMLhCH

What I meant was one of them may be wrong, eg you may have typed timer instead of time or vice versa.

  1. Have you tried a different port, e.g. port 9000 or something higher?

  2. In the tutorial, the child is added via deferred call, but you’re not doing that. Also, the tutorial calls set_multiplayer_authority before adding the child, but you are calling it on _enter_tree(). Not sure if these make a difference, but they are diverging from the tutorial.

  3. Are you sure you need to add the level every time a player joins?

Wow. If that is a tutorial then it is a bad one. Look at the huge nested if’s. Guaranteed to confuse.

This is why what is probably a simple bug is impossible to track down. Your physics_process should look something more like:

func _physics_process(delta: float) -> void:
    if !is_multiplayer_authority():
        return

    handle_input()
    handle_attack_state(delta)
    handle_cooldowns(delta)
    handle_vertical_movement(delta)
    handle_horizontal_movement(delta)

    move_and_slide()

A good exercise for you would be to refactor this code now. Your bug will probably drop out or become startlingly obvious.

EDIT: Ok the tutorial might be ok, I am not judging it as I have not looked at it, since the multiplayer menu looks much better organised. But that physics process is a mess.

EDIT 2: I took a quick look and it is indeed about multiplayer, so the tutorial was not really about movement controls, so I suppose that is why it got messy for you.

Today I’ll show you how to do multiplayer in Godot in a SUPER easy way

breaking your code down into smaller, easier to parse sections will make it easier to fix and to see what’s wrong. i fear you’re going to have to start from scratch and, rather than doing one long ifelse statement, add a bunch of smaller functions that are for specific things like player movement and attacks (and also make player-specific code its own .gd file to keep it separate from the multiplayer stuff)

  1. The online works, because the player joins and all of that

  2. I change the code following that tutorial, but nothing changes

  3. How i change that?