132 lines
4.8 KiB
C#
132 lines
4.8 KiB
C#
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;
|
||
}
|
||
} |