Godot Version
4.3
Question
Hi, I’m following this really cool tutorial here https://www.youtube.com/watch?v=n8D3vEx7NAE&t=1s and i’ve gotten to the multiplayer setup, at this point https://youtu.be/n8D3vEx7NAE?t=1845.
my problem is that when I am playing from the host, it looks like I’m controlling the peer, in both the host and client window.
If I’m playing from the client, It looks like I’m playing the local character in both the host and client window.
From what I can tell, I’ve set authority up correctly, and also replication, but something’s wrong.
world.gd
# https://youtu.be/n8D3vEx7NAE?t=1488
extends Node
@onready var main_menu = $CanvasLayer/MainMenu
@onready var address_entry = $CanvasLayer/MainMenu/MarginContainer/VBoxContainer/AddressEntry
const Player = preload("res://player.tscn")
const PORT = 9999
var enet_peer = ENetMultiplayerPeer.new()
func _unhandled_input(_event: InputEvent) -> void:
if Input.is_action_just_pressed("quit"):
get_tree().quit()
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta: float) -> void:
pass
func _on_host_button_pressed() -> void:
main_menu.hide()
enet_peer.create_server(PORT)
multiplayer.multiplayer_peer = enet_peer
multiplayer.peer_connected.connect(add_player)
add_player(multiplayer.get_unique_id())
func _on_join_button_pressed() -> void:
main_menu.hide()
enet_peer.create_client("localhost", PORT)
multiplayer.multiplayer_peer = enet_peer
func add_player(peer_id):
var player = Player.instantiate()
player.name = str(peer_id)
add_child(player)
player.gd
extends CharacterBody3D
@onready var camera = $Camera3D
@onready var anim_player = $AnimationPlayer
@onready var muzzle_flash = $Camera3D/Pistol/MuzzleFlash
const SPEED = 10
const JUMP_VELOCITY = 10
#Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = 20.0
func _enter_tree() -> void:
set_multiplayer_authority(str(name).to_int())
func _ready() -> void:
if not is_multiplayer_authority(): return
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
camera.current = true
func _unhandled_input(event: InputEvent) -> void:
if not is_multiplayer_authority(): return
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * .005)
camera.rotate_x(-event.relative.y * .005)
camera.rotation.x = clamp(camera.rotation.x, -PI/2, PI/2)
if Input.is_action_just_pressed("shoot") \
and anim_player.current_animation != "shoot":
play_shoot_effects.rpc()
func _physics_process(delta: float) -> void:
if not is_multiplayer_authority(): return
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var input_dir = Input.get_vector("left", "right", "up", "down")
var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
if anim_player.current_animation == "shoot":
pass
elif input_dir != Vector2.ZERO and is_on_floor():
anim_player.play("move")
else:
anim_player.play("idle")
move_and_slide()
@rpc("call_local")
func play_shoot_effects():
anim_player.stop()
anim_player.play("shoot")
muzzle_flash.restart()
muzzle_flash.emitting = true
func _on_animation_player_animation_finished(anim_name: StringName) -> void:
if anim_name == "shoot":
anim_player.play("idle")