multyplayer
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
extends Node3D
|
||||
|
||||
## One instance per connected peer. The owning peer is the multiplayer
|
||||
## authority. The local (authority) player builds the full XR rig from
|
||||
## XROrigin.tscn and feeds its head/hand poses into synced properties; remote
|
||||
## players show a lightweight avatar driven by those synced poses.
|
||||
|
||||
const RIG_SCENE := preload("res://XROrigin.tscn")
|
||||
|
||||
# Synced avatar pose. Authority writes these from the XR trackers each frame;
|
||||
# remotes read them onto the Avatar. net_heartbeat is a monotonic counter used
|
||||
# to confirm replication is live (also handy for debugging).
|
||||
@export var head_xform: Transform3D = Transform3D.IDENTITY
|
||||
@export var left_xform: Transform3D = Transform3D.IDENTITY
|
||||
@export var right_xform: Transform3D = Transform3D.IDENTITY
|
||||
@export var net_heartbeat: int = 0
|
||||
|
||||
var _rig: Node3D
|
||||
var _camera: Node3D
|
||||
var _left: Node3D
|
||||
var _right: Node3D
|
||||
var _is_local := false
|
||||
|
||||
@onready var _avatar: Node3D = $Avatar
|
||||
@onready var _avatar_head: Node3D = $Avatar/Head
|
||||
@onready var _avatar_left: Node3D = $Avatar/LeftHand
|
||||
@onready var _avatar_right: Node3D = $Avatar/RightHand
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
# The spawner names each player by its owning peer id.
|
||||
set_multiplayer_authority(str(name).to_int())
|
||||
|
||||
|
||||
# (replication config is authored in Player.tscn's MultiplayerSynchronizer)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_is_local = is_multiplayer_authority()
|
||||
if _is_local:
|
||||
_setup_local()
|
||||
else:
|
||||
_setup_remote()
|
||||
if Engine.has_singleton("NetworkManager") or get_node_or_null("/root/NetworkManager"):
|
||||
NetworkManager.log_line("Player %s ready (authority=%d local=%s)" % [name, get_multiplayer_authority(), str(_is_local)])
|
||||
|
||||
|
||||
func _setup_local() -> void:
|
||||
# We see through the headset; hide our own avatar mesh.
|
||||
_avatar.visible = false
|
||||
_rig = RIG_SCENE.instantiate()
|
||||
add_child(_rig)
|
||||
_camera = _rig.get_node_or_null("XRCamera3D")
|
||||
_left = _rig.get_node_or_null("XRControllerLeftHand")
|
||||
_right = _rig.get_node_or_null("XRControllerRightHand")
|
||||
_enable_xr()
|
||||
|
||||
|
||||
func _enable_xr() -> void:
|
||||
var xr := XRServer.find_interface("OpenXR")
|
||||
if xr and xr.is_initialized():
|
||||
get_viewport().use_xr = true
|
||||
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
|
||||
|
||||
|
||||
func _setup_remote() -> void:
|
||||
_avatar.visible = true
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if _is_local:
|
||||
if _camera:
|
||||
head_xform = _camera.global_transform
|
||||
left_xform = _left.global_transform
|
||||
right_xform = _right.global_transform
|
||||
net_heartbeat += 1
|
||||
else:
|
||||
_avatar_head.global_transform = head_xform
|
||||
_avatar_left.global_transform = left_xform
|
||||
_avatar_right.global_transform = right_xform
|
||||
Reference in New Issue
Block a user