115 lines
3.2 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|