Kursach_StealthAction/Assets/Scripts/ObjectThrower.cs

132 lines
4.8 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;
// Обязательно добавляем библиотеку новой системы ввода
using UnityEngine.InputSystem;
public class ObjectThrower : MonoBehaviour
{
[Header("Настройки подбора")]
public float pickupRange = 3f;
public Transform holdPosition;
public LayerMask pickupLayer;
[Header("Настройки броска")]
public float chargeRate = 15f;
public float maxThrowForce = 25f;
private float currentThrowForce = 0f;
private GameObject heldObject;
private Rigidbody heldObjectRb;
private Camera mainCamera;
void Start()
{
mainCamera = Camera.main;
}
void Update()
{
// Защита от ошибок, если клавиатура не подключена
if (Keyboard.current == null) return;
// 1. Подбор и выбрасывание (вместо Input.GetKeyDown)
if (Keyboard.current.eKey.wasPressedThisFrame)
{
if (heldObject == null) TryPickup();
else DropObject();
}
// 2. Накопление силы и бросок
if (heldObject != null)
{
// Пока клавиша зажата (вместо Input.GetKey)
if (Keyboard.current.qKey.isPressed)
{
currentThrowForce += chargeRate * Time.deltaTime;
currentThrowForce = Mathf.Clamp(currentThrowForce, 0, maxThrowForce);
}
// Когда клавишу отпустили (вместо Input.GetKeyUp)
if (Keyboard.current.qKey.wasReleasedThisFrame)
{
ThrowObject();
}
}
}
private void TryPickup()
{
// Создаем луч из камеры вперед
Ray ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward);
// SphereCastAll пускает "толстый" луч радиусом 0.5 метра на длину 20 метров.
// Он пробивает спину игрока и собирает ВСЕ объекты на пути в массив hits.
RaycastHit[] hits = Physics.SphereCastAll(ray, 0.5f, 20f, pickupLayer);
// Перебираем все, во что врезался наш толстый луч
foreach (RaycastHit hit in hits)
{
// Ищем первый попавшийся предмет с нужным тегом
if (hit.collider.CompareTag("Throwable"))
{
// Проверяем, стоит ли персонаж достаточно близко к предмету (pickupRange)
float distanceToPlayer = Vector3.Distance(transform.position, hit.transform.position);
if (distanceToPlayer <= pickupRange)
{
heldObject = hit.collider.gameObject;
heldObjectRb = heldObject.GetComponent<Rigidbody>();
// Отключаем физику на время удержания
heldObjectRb.isKinematic = true;
heldObjectRb.useGravity = false;
// Прикрепляем к руке
heldObject.transform.SetParent(holdPosition);
heldObject.transform.localPosition = Vector3.zero;
heldObject.transform.localRotation = Quaternion.identity;
// Как только успешно взяли предмет — прерываем цикл, чтобы не взять два сразу
break;
}
}
}
}
private void DropObject()
{
heldObject.transform.SetParent(null);
heldObjectRb.isKinematic = false;
heldObjectRb.useGravity = true;
heldObject = null;
heldObjectRb = null;
currentThrowForce = 0f;
}
private void ThrowObject()
{
heldObject.transform.SetParent(null);
heldObjectRb.isKinematic = false;
heldObjectRb.useGravity = true;
Ray ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward);
Vector3 targetPoint;
if (Physics.Raycast(ray, out RaycastHit hit, 50f))
{
targetPoint = hit.point;
}
else
{
targetPoint = ray.GetPoint(50f);
}
Vector3 throwDirection = (targetPoint - holdPosition.position).normalized;
heldObjectRb.AddForce(throwDirection * currentThrowForce, ForceMode.Impulse);
heldObject = null;
heldObjectRb = null;
currentThrowForce = 0f;
}
}