using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; public sealed class PlayerInteractionController : NetworkBehaviour, IPlayerSystem { [SerializeField, Min(0.1f)] private float interactionDistance = 3f; [SerializeField] private LayerMask interactionMask = ~0; private Camera playerCamera; private IInteractable focusedInteractable; private bool isInitialized; public void Initialize(PlayerFacade facade) { playerCamera = GetComponentInChildren(true); isInitialized = playerCamera != null; } private void Update() { if (!isInitialized || !IsOwner || Keyboard.current == null) return; focusedInteractable = FindFocusedInteractable(); if (Keyboard.current.eKey.wasPressedThisFrame && focusedInteractable != null && focusedInteractable.IsInteractionAvailable) { focusedInteractable.RequestInteraction(); } } private IInteractable FindFocusedInteractable() { Ray ray = new(playerCamera.transform.position, playerCamera.transform.forward); if (!Physics.Raycast(ray, out RaycastHit hit, interactionDistance, interactionMask, QueryTriggerInteraction.Collide)) return null; foreach (MonoBehaviour component in hit.collider.GetComponentsInParent()) { if (component is IInteractable interactable) return interactable; } return null; } private void OnGUI() { if (!IsOwner || focusedInteractable == null) return; GUIStyle style = new(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontSize = 16, normal = { textColor = Color.white } }; string prompt = focusedInteractable.IsInteractionAvailable ? "[E] " + focusedInteractable.InteractionPrompt : "In use"; Rect area = new(0f, Screen.height * 0.62f, Screen.width, 28f); GUI.Label(area, prompt, style); } }