namespace Player { using System.Collections; using System.Collections.Generic; using UnityEngine; public class TruckBedVisuals : MonoBehaviour { [Header("Настройки кузова")] public Transform bedStartPoint; public GameObject visualBoxPrefab; [Header("Сетка укладки")] public int columns = 3; public int rows = 3; [Header("Размеры и отступы ")] public bool uniformScale = true; public Vector3 boxSize = new Vector3(1f, 1f, 1f); public Vector3 boxPadding = new Vector3(0.05f, 0.05f, 0.05f); [Header("Отрисовка в редакторе")] public int gizmoPreviewLayers = 3; [Header("Физика выпадения")] public float dropUpForce = 5f; public float dropBackForce = 15f; public float dropTorque = 10f; private Stack _stackedBoxes = new Stack(); private Collider _carCollider; private void OnValidate() { if (uniformScale) { boxSize.y = boxSize.x; boxSize.z = boxSize.x; boxPadding.y = boxPadding.x; boxPadding.z = boxPadding.x; } } void Awake() { _carCollider = GetComponent(); } private void OnEnable() { GameEvents.OnBoxAddedToTruck += AddBox; GameEvents.OnBoxLostFromTruck += DropBox; } private void OnDisable() { GameEvents.OnBoxAddedToTruck -= AddBox; GameEvents.OnBoxLostFromTruck -= DropBox; } private void OnDrawGizmos() { if (bedStartPoint == null) return; Gizmos.color = new Color(0f, 1f, 0f, 0.5f); Vector3 step = boxSize + boxPadding; // Сохраняем старую матрицу и применяем трансформацию якоря кузова. // Теперь сетка будет крутиться и двигаться вместе с машиной! Matrix4x4 oldMatrix = Gizmos.matrix; Gizmos.matrix = bedStartPoint.localToWorldMatrix; for (int layer = 0; layer < gizmoPreviewLayers; layer++) { for (int x = 0; x < columns; x++) { for (int z = 0; z < rows; z++) { Vector3 boxCenter = new Vector3(x * step.x, layer * step.y, -z * step.z); Gizmos.DrawWireCube(boxCenter, boxSize); } } } Gizmos.matrix = oldMatrix; } private void AddBox() { if (visualBoxPrefab == null || bedStartPoint == null) return; int index = _stackedBoxes.Count; int layer = index / (columns * rows); int indexInLayer = index % (columns * rows); int x = indexInLayer % columns; int z = indexInLayer / columns; Vector3 step = boxSize + boxPadding; Vector3 localPos = new Vector3(x * step.x, layer * step.y, -z * step.z); GameObject newBox = SimpleObjectPool.Instance.Get(visualBoxPrefab, bedStartPoint.position, bedStartPoint.rotation); newBox.transform.SetParent(bedStartPoint); newBox.transform.localPosition = localPos; newBox.transform.localRotation = Quaternion.identity; newBox.transform.localScale = boxSize; Rigidbody rb = newBox.GetComponent(); if (rb != null) rb.isKinematic = true; Collider coll = newBox.GetComponent(); if (coll != null) coll.enabled = false; _stackedBoxes.Push(newBox); } private void DropBox() { if (_stackedBoxes.Count == 0) return; GameObject boxToDrop = _stackedBoxes.Pop(); boxToDrop.transform.SetParent(null); Collider coll = boxToDrop.GetComponent(); if (coll != null) { coll.enabled = true; if (_carCollider != null) Physics.IgnoreCollision(coll, _carCollider); } Rigidbody rb = boxToDrop.GetComponent(); if (rb != null) { rb.isKinematic = false; Rigidbody carRb = GetComponent(); if (carRb != null) rb.linearVelocity = carRb.linearVelocity; Vector3 force = transform.up * dropUpForce - transform.forward * dropBackForce; rb.AddForce(force, ForceMode.Impulse); rb.AddTorque(Random.insideUnitSphere * dropTorque, ForceMode.Impulse); } StartCoroutine(ReturnBoxToPool(boxToDrop, 3f)); } IEnumerator ReturnBoxToPool(GameObject box, float delay) { yield return new WaitForSeconds(delay); SimpleObjectPool.Instance.ReturnToPool(visualBoxPrefab, box); } } }