107 lines
4.6 KiB
C#
107 lines
4.6 KiB
C#
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// Показывает модель активного предмета хотбара в руке персонажа.
|
||
/// Принцип — как в Minecraft: выбранный слот хотбара = предмет в правой руке.
|
||
/// Добавьте на Player, назначьте handBone в Inspector.
|
||
/// </summary>
|
||
public class HandEquipSystem : MonoBehaviour
|
||
{
|
||
[Header("Hand Setup")]
|
||
[Tooltip("Кость правой руки из скелета персонажа")]
|
||
public Transform handBone;
|
||
|
||
[Tooltip("Смещение предмета относительно кости руки")]
|
||
public Vector3 itemOffset = Vector3.zero;
|
||
|
||
[Tooltip("Поворот предмета в руке (euler)")]
|
||
public Vector3 itemRotation = Vector3.zero;
|
||
|
||
[Tooltip("Масштаб предмета в руке")]
|
||
public Vector3 itemScale = Vector3.one;
|
||
|
||
// ── Приватные поля ────────────────────────────────────────────────────────
|
||
private GameObject _currentHandItem;
|
||
|
||
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
||
void Start()
|
||
{
|
||
// Подписываемся на смену слота хотбара
|
||
if (PlayerInput.Instance != null)
|
||
PlayerInput.Instance.OnHotbarSelect += OnHotbarSlotSelected;
|
||
|
||
// Подписываемся на изменение слотов (drag-drop, добавление/удаление)
|
||
if (InventoryEvents.Instance != null)
|
||
InventoryEvents.Instance.OnSlotChanged.AddListener(OnSlotChanged);
|
||
|
||
UpdateHandItem();
|
||
}
|
||
|
||
void OnDestroy()
|
||
{
|
||
if (PlayerInput.Instance != null)
|
||
PlayerInput.Instance.OnHotbarSelect -= OnHotbarSlotSelected;
|
||
|
||
if (InventoryEvents.Instance != null)
|
||
InventoryEvents.Instance.OnSlotChanged.RemoveListener(OnSlotChanged);
|
||
}
|
||
|
||
// ── Обработчики событий ───────────────────────────────────────────────────
|
||
|
||
private void OnHotbarSlotSelected(int index) => UpdateHandItem();
|
||
|
||
private void OnSlotChanged(int slotIndex, string itemId) => UpdateHandItem();
|
||
|
||
// ── Логика обновления предмета в руке ────────────────────────────────────
|
||
|
||
/// <summary>
|
||
/// Обновить объект в руке под текущий выбранный слот хотбара.
|
||
/// Можно вызвать вручную если нужно принудительное обновление.
|
||
/// </summary>
|
||
public void UpdateHandItem()
|
||
{
|
||
// Уничтожить старый объект в руке
|
||
if (_currentHandItem != null)
|
||
{
|
||
Destroy(_currentHandItem);
|
||
_currentHandItem = null;
|
||
}
|
||
|
||
if (handBone == null)
|
||
{
|
||
Debug.LogWarning("[HandEquipSystem] handBone не назначен!");
|
||
return;
|
||
}
|
||
|
||
if (InventoryManager.Instance == null) return;
|
||
|
||
var item = InventoryManager.Instance.GetSelectedHotbarItem();
|
||
if (item == null || item.modelPrefab == null) return;
|
||
|
||
// Создать модель как дочерний объект кости руки
|
||
_currentHandItem = Instantiate(item.modelPrefab, handBone);
|
||
_currentHandItem.name = $"HandItem_{item.itemName}";
|
||
_currentHandItem.transform.localPosition = itemOffset;
|
||
_currentHandItem.transform.localEulerAngles = itemRotation;
|
||
_currentHandItem.transform.localScale = itemScale;
|
||
|
||
// Отключить физику и коллайдеры — предмет в руке не должен взаимодействовать с миром
|
||
foreach (var col in _currentHandItem.GetComponentsInChildren<Collider>())
|
||
col.enabled = false;
|
||
foreach (var rb in _currentHandItem.GetComponentsInChildren<Rigidbody>())
|
||
rb.isKinematic = true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Убрать предмет из руки (например когда открыт инвентарь).
|
||
/// </summary>
|
||
public void ClearHandItem()
|
||
{
|
||
if (_currentHandItem != null)
|
||
{
|
||
Destroy(_currentHandItem);
|
||
_currentHandItem = null;
|
||
}
|
||
}
|
||
}
|