156 lines
5.2 KiB
C#
156 lines
5.2 KiB
C#
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<GameObject> _stackedBoxes = new Stack<GameObject>();
|
||
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<Collider>();
|
||
}
|
||
|
||
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<Rigidbody>();
|
||
if (rb != null) rb.isKinematic = true;
|
||
|
||
Collider coll = newBox.GetComponent<Collider>();
|
||
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<Collider>();
|
||
if (coll != null)
|
||
{
|
||
coll.enabled = true;
|
||
if (_carCollider != null) Physics.IgnoreCollision(coll, _carCollider);
|
||
}
|
||
|
||
Rigidbody rb = boxToDrop.GetComponent<Rigidbody>();
|
||
if (rb != null)
|
||
{
|
||
rb.isKinematic = false;
|
||
|
||
Rigidbody carRb = GetComponent<Rigidbody>();
|
||
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);
|
||
}
|
||
}
|
||
} |