Files
FORT-BO/Assets/CONTENT/Game/Scripts/Player/PlayerInteractionController.cs
T
2026-08-07 11:40:20 +03:00

102 lines
2.9 KiB
C#

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 IPlayerInteractionSession activeSession;
private bool activeSessionReleaseRequested;
private bool isInitialized;
public void Initialize(PlayerFacade facade)
{
playerCamera = GetComponentInChildren<Camera>(true);
isInitialized = playerCamera != null;
}
private void Update()
{
if (!isInitialized || !IsOwner || Keyboard.current == null)
return;
if (PlayerInteractionSessionRegistry.TryGetControlledSession(
OwnerClientId,
out activeSession))
{
focusedInteractable = null;
if (!Keyboard.current.eKey.isPressed && !activeSessionReleaseRequested)
{
activeSessionReleaseRequested = true;
activeSession.RequestRelease();
}
return;
}
activeSession = null;
activeSessionReleaseRequested = false;
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<MonoBehaviour>())
{
if (component is IInteractable interactable)
return interactable;
}
return null;
}
private void OnGUI()
{
if (!IsOwner)
return;
if (activeSession != null)
{
DrawPrompt(activeSession.ReleasePrompt);
return;
}
if (focusedInteractable == null)
return;
string prompt = focusedInteractable.IsInteractionAvailable
? "[E] " + focusedInteractable.InteractionPrompt
: "In use";
DrawPrompt(prompt);
}
private static void DrawPrompt(string prompt)
{
GUIStyle style = new(GUI.skin.label)
{
alignment = TextAnchor.MiddleCenter,
fontSize = 16,
normal = { textColor = Color.white }
};
Rect area = new(0f, Screen.height * 0.62f, Screen.width, 28f);
GUI.Label(area, prompt, style);
}
}