Files
ScienceLab.WeightAndMass/Assets/Scripts/BeakerContainer.cs
2026-04-07 03:14:32 +03:00

115 lines
3.2 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BeakerContainer : MonoBehaviour
{
[System.Serializable]
public class LiquidLayer
{
public LiquidContainer.LiquidType liquidType;
public Color color;
public float density;
public float amount;
}
[SerializeField] private GameObject _layerTemplate;
[SerializeField] private float _emptyMassKg = 0.15f;
[SerializeField] private float _volumeLiters = 0.25f;
[SerializeField] public float capacity = 1f;
public List<LiquidLayer> layers = new List<LiquidLayer>();
private List<GameObject> _layerObjects = new List<GameObject>();
private Rigidbody _rb;
public bool IsFull() => TotalAmount() >= 1f;
public bool IsEmpty() => TotalAmount() <= 0f;
public float TotalAmount()
{
float total = 0f;
foreach (var l in layers) total += l.amount;
return total;
}
private void Awake()
{
_rb = GetComponent<Rigidbody>();
if (_layerTemplate != null)
_layerTemplate.SetActive(false);
}
public void AddLiquid(Color color, float amount, float density, LiquidContainer.LiquidType type)
{
float canAdd = Mathf.Clamp(amount, 0f, 1f - TotalAmount());
if (canAdd <= 0f) return;
LiquidLayer existing = layers.Find(l => l.liquidType == type);
if (existing != null)
{
existing.amount += canAdd;
}
else
{
layers.Add(new LiquidLayer
{
liquidType = type,
color = color,
density = density,
amount = canAdd
});
}
layers.Sort((a, b) => b.density.CompareTo(a.density));
UpdateVisual();
UpdateMass();
}
public void UpdateMass()
{
if (_rb == null) return;
float liquidMass = 0f;
foreach (var l in layers)
liquidMass += l.amount * _volumeLiters * l.density;
_rb.mass = _emptyMassKg + liquidMass;
}
public void UpdateVisual()
{
foreach (var obj in _layerObjects)
Destroy(obj);
_layerObjects.Clear();
if (_layerTemplate == null || layers.Count == 0) return;
float yOffset = 0f;
foreach (var layer in layers)
{
GameObject go = Instantiate(_layerTemplate, _layerTemplate.transform.parent);
go.SetActive(true);
Vector3 pos = _layerTemplate.transform.localPosition;
pos.y = yOffset;
go.transform.localPosition = pos;
Vector3 scale = _layerTemplate.transform.localScale;
scale.y = Mathf.Max(0.01f, layer.amount);
go.transform.localScale = scale;
Renderer rend = go.GetComponent<Renderer>();
if (rend != null)
{
Material mat = new Material(rend.sharedMaterial);
if (mat.HasProperty("_c1")) mat.SetColor("_c1", layer.color);
if (mat.HasProperty("_c2")) mat.SetColor("_c2", layer.color);
rend.material = mat;
}
yOffset += scale.y;
_layerObjects.Add(go);
}
}
}