Perekyp/Assets/Scripts/Player/Interactor/PlayerInteractor.cs

166 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
public class PlayerInteractor : MonoBehaviour
{
[Header("Настройки луча")]
[SerializeField] private float interactRange = 3f;
[SerializeField] private LayerMask interactableLayer;
[Header("Клавиши управления")]
[SerializeField] private KeyCode primaryKey = KeyCode.E;
[SerializeField] private KeyCode secondaryKey = KeyCode.R;
[SerializeField] private KeyCode enterVehicleKey = KeyCode.F;
[Header("Ссылки")]
[SerializeField] private UIManager uiManager;
private CarPart lastHoveredPart;
private void Awake()
{
if (uiManager == null)
uiManager = FindAnyObjectByType<UIManager>();
}
private void OnDisable()
{
ResetProgressTargets();
if (uiManager != null) uiManager.HidePrompt();
}
private void Update()
{
if (CarJack.ActiveJackInHand != null)
{
uiManager?.ShowPrompt(CarJack.ActiveJackInHand.GetPlacementPrompt());
return;
}
Ray ray = new Ray(transform.position, transform.forward);
if (Physics.Raycast(ray, out RaycastHit hit, interactRange, interactableLayer, QueryTriggerInteraction.Collide))
{
GameObject playerRoot = transform.root.gameObject;
// 1. ПРИОРИТЕТ БОЛТАМ: проверяем, не целимся ли мы в колесный болт (даже сквозь коллайдер шины)
WheelBolt bolt = hit.collider.GetComponent<WheelBolt>();
if (bolt == null)
{
Collider[] nearCols = Physics.OverlapSphere(hit.point, 0.06f, interactableLayer, QueryTriggerInteraction.Collide);
foreach (var c in nearCols)
{
bolt = c.GetComponent<WheelBolt>();
if (bolt != null) break;
}
}
if (bolt != null)
{
ResetProgressTargets();
string boltPrompt = bolt.GetPrompt();
if (!string.IsNullOrEmpty(boltPrompt))
uiManager?.ShowPrompt(boltPrompt);
else
uiManager?.HidePrompt();
return;
}
// 2. Обычные объекты, детали и авто
IInteractable interactable = hit.collider.GetComponentInParent<IInteractable>();
VehicleInteraction vehicle = hit.collider.GetComponentInParent<VehicleInteraction>();
CarPart part = hit.collider.GetComponentInParent<CarPart>();
CarPartMountZone mountZone = hit.collider.GetComponentInParent<CarPartMountZone>();
if (part != lastHoveredPart)
{
ResetProgressTargets();
lastHoveredPart = part;
}
if (interactable != null || vehicle != null)
{
// Посадка в авто (F)
if (Input.GetKeyDown(enterVehicleKey) && vehicle != null)
{
vehicle.Interact(playerRoot);
return;
}
// Зона обратной установки детали (обрабатывается внутри CarPartMountZone)
if (mountZone != null)
{
if (Input.GetKeyDown(primaryKey))
mountZone.Interact(playerRoot);
}
// Работа с деталью (снятие / открытие / подбор с земли)
else if (part != null)
{
if (part.State == PartState.Dropped)
{
if (Input.GetKeyDown(primaryKey))
part.Interact(playerRoot);
}
else if (part.State == PartState.Installed)
{
bool hasAnimator = part.GetComponent<CarPartAnimator>() != null;
if (hasAnimator)
{
if (Input.GetKeyDown(primaryKey))
part.Interact(playerRoot);
if (Input.GetKey(secondaryKey))
part.ProcessUnbolting(playerRoot, Time.deltaTime);
else
part.ResetUnbolt();
}
else
{
if (Input.GetKey(primaryKey))
part.ProcessUnbolting(playerRoot, Time.deltaTime);
else
part.ResetUnbolt();
}
}
}
else if (interactable != null && Input.GetKeyDown(primaryKey))
{
interactable.Interact(playerRoot);
}
string finalPrompt = BuildPrompt(vehicle, interactable);
if (!string.IsNullOrEmpty(finalPrompt))
uiManager?.ShowPrompt(finalPrompt);
else
uiManager?.HidePrompt();
return;
}
}
ResetProgressTargets();
uiManager?.HidePrompt();
}
private string BuildPrompt(VehicleInteraction vehicle, IInteractable interactable)
{
string partPrompt = (interactable != null && !(interactable is VehicleInteraction))
? interactable.GetPrompt()
: string.Empty;
bool canEnter = vehicle != null && !vehicle.isPlayerInside;
if (canEnter && !string.IsNullOrEmpty(partPrompt))
return $"[F] Сесть | {partPrompt}";
if (canEnter)
return "[F] Сесть в машину";
return partPrompt;
}
private void ResetProgressTargets()
{
if (lastHoveredPart != null) lastHoveredPart.ResetUnbolt();
lastHoveredPart = null;
}
}