150 lines
4.9 KiB
C#
150 lines
4.9 KiB
C#
using UnityEngine;
|
||
using UnityEngine.InputSystem;
|
||
|
||
/// <summary>
|
||
/// Интерактивная сюжетная записка в 3D мире.
|
||
/// Игрок может подойти, увидеть подсказку и нажать [E] для открытия полноэкранного документа.
|
||
/// </summary>
|
||
public class NotePickup : MonoBehaviour
|
||
{
|
||
[Header("Настройки кода лифта")]
|
||
[Tooltip("Порядковый номер в коде: 0 = 1-я цифра, 1 = 2-я цифра, 2 = 3-я цифра, 3 = 4-я цифра")]
|
||
public int digitPosition = 0;
|
||
|
||
[Header("Сюжетное описание")]
|
||
public string noteTitle = "ЗАПИСКА ИССЛЕДОВАТЕЛЯ";
|
||
public string sectorName = "СЕКТОР АРХИВА";
|
||
[TextArea(3, 8)]
|
||
public string storyText = "Мы заблокировали лифт в нижний уровень, чтобы задержать биомассу. Если кто-то выжил, введите код в терминал...";
|
||
|
||
[Header("Дистанция взаимодействия")]
|
||
public float interactionDistance = 3.6f;
|
||
|
||
[Header("Визуальное покачивание и свечение")]
|
||
public bool animateHover = true;
|
||
public float hoverSpeed = 2.0f;
|
||
public float hoverHeight = 0.05f;
|
||
|
||
private Vector3 initialPos;
|
||
private static Transform cachedPlayerTransform;
|
||
|
||
private void Start()
|
||
{
|
||
initialPos = transform.position;
|
||
LocatePlayer();
|
||
|
||
var col = GetComponent<Collider>();
|
||
if (col == null)
|
||
{
|
||
var sc = gameObject.AddComponent<SphereCollider>();
|
||
sc.isTrigger = true;
|
||
sc.radius = interactionDistance;
|
||
}
|
||
}
|
||
|
||
private Transform LocatePlayer()
|
||
{
|
||
if (cachedPlayerTransform != null) return cachedPlayerTransform;
|
||
|
||
var pm = Object.FindAnyObjectByType<PlayerMovement>();
|
||
if (pm != null) { cachedPlayerTransform = pm.transform; return cachedPlayerTransform; }
|
||
|
||
var ph = Object.FindAnyObjectByType<PlayerHealth>();
|
||
if (ph != null) { cachedPlayerTransform = ph.transform; return cachedPlayerTransform; }
|
||
|
||
var pTag = GameObject.FindWithTag("Player");
|
||
if (pTag != null) { cachedPlayerTransform = pTag.transform; return cachedPlayerTransform; }
|
||
|
||
var pName = GameObject.Find("Player");
|
||
if (pName != null) { cachedPlayerTransform = pName.transform; return cachedPlayerTransform; }
|
||
|
||
if (Camera.main != null) { return Camera.main.transform; }
|
||
|
||
return null;
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
if (animateHover)
|
||
{
|
||
float newY = initialPos.y + Mathf.Sin(Time.time * hoverSpeed) * hoverHeight;
|
||
transform.position = new Vector3(initialPos.x, newY, initialPos.z);
|
||
}
|
||
|
||
if (NoteViewerUI.Instance != null && NoteViewerUI.Instance.IsOpen) return;
|
||
if (Time.timeScale == 0f) return;
|
||
|
||
Transform player = LocatePlayer();
|
||
if (player == null) return;
|
||
|
||
float dist3D = Vector3.Distance(transform.position, player.position);
|
||
float distXZ = Vector2.Distance(new Vector2(transform.position.x, transform.position.z),
|
||
new Vector2(player.position.x, player.position.z));
|
||
|
||
bool inRange = dist3D <= interactionDistance || distXZ <= (interactionDistance * 0.9f);
|
||
|
||
if (inRange)
|
||
{
|
||
if (CheckInteractInput())
|
||
{
|
||
Interact();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void OnTriggerStay(Collider other)
|
||
{
|
||
if (NoteViewerUI.Instance != null && NoteViewerUI.Instance.IsOpen) return;
|
||
if (Time.timeScale == 0f) return;
|
||
|
||
if (other.CompareTag("Player") || other.GetComponentInParent<PlayerMovement>() != null)
|
||
{
|
||
if (CheckInteractInput())
|
||
{
|
||
Interact();
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool CheckInteractInput()
|
||
{
|
||
var keyboard = Keyboard.current;
|
||
if (keyboard != null)
|
||
{
|
||
if (keyboard.eKey.wasPressedThisFrame ||
|
||
keyboard.fKey.wasPressedThisFrame ||
|
||
keyboard.enterKey.wasPressedThisFrame)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||
if (Input.GetKeyDown(KeyCode.E) || Input.GetKeyDown(KeyCode.F) || Input.GetKeyDown(KeyCode.Return))
|
||
{
|
||
return true;
|
||
}
|
||
#endif
|
||
|
||
return false;
|
||
}
|
||
|
||
public void Interact()
|
||
{
|
||
int digit = 0;
|
||
if (LevelCodeManager.Instance != null)
|
||
{
|
||
digit = LevelCodeManager.Instance.GetDigit(digitPosition);
|
||
}
|
||
|
||
if (NoteViewerUI.Instance != null)
|
||
{
|
||
NoteViewerUI.Instance.OpenNote(digitPosition, digit, sectorName, noteTitle, storyText);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("[NotePickup] NoteViewerUI.Instance is NULL!");
|
||
}
|
||
}
|
||
}
|