using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.Pool; namespace BlueWater { public class LiquidController : MonoBehaviour { [SerializeField] private Renderer _liquidRenderer; [SerializeField, Required] private Liquid _liquidObject; [SerializeField, Required] private Transform _spawnTransform; [SerializeField] private Transform _spawnLocation; [SerializeField] private int _objectPoolCount = 1000; [SerializeField] private Color _liquidColor = new(0f, 0.7294118f, 1f, 1f); private IObjectPool _objectPool; private List _activeLiquids = new(); private Dictionary _colorTimes = new(); private bool _isPouring; private float _startTime = float.PositiveInfinity; private Material _material; // Hashes private static readonly int _colorHash = Shader.PropertyToID("_Color"); private void Awake() { _objectPool = new ObjectPool(CreateObject, OnGetObject, OnReleaseObject, OnDestroyObject, maxSize: _objectPoolCount); } private void Start() { _material = Instantiate(_liquidRenderer.material); _liquidRenderer.material = _material; } private void Update() { if (_isPouring) { _objectPool.Get(); if (_colorTimes.ContainsKey(_liquidColor)) { _colorTimes[_liquidColor] += Time.time - _startTime; } else { _colorTimes[_liquidColor] = Time.time - _startTime; } _startTime = Time.time; _liquidRenderer.material.SetColor(_colorHash, MixColorsByTime()); } } private Liquid CreateObject() { var instance = Instantiate(_liquidObject, _spawnTransform.position, Quaternion.identity, _spawnLocation); instance.SetManagedPool(_objectPool); instance.SetColor(_liquidColor); return instance; } private void OnGetObject(Liquid liquid) { liquid.transform.position = _spawnTransform.position; liquid.transform.rotation = Quaternion.identity; liquid.gameObject.SetActive(true); _activeLiquids.Add(liquid); } private void OnReleaseObject(Liquid liquid) { liquid.gameObject.SetActive(false); _activeLiquids.Remove(liquid); } private void OnDestroyObject(Liquid liquid) { Destroy(liquid.gameObject); _activeLiquids.Remove(liquid); } [Button("기본 색상")] private void DefaultColor() => _liquidColor = new Color(0f, 0.7294118f, 1f, 1f); public void ReleaseAllObject() { // 뒤에서부터 Remove해야 오류가 없음 for (var i = _activeLiquids.Count - 1; i >= 0; i--) { _activeLiquids[i].Destroy(); } _colorTimes.Clear(); } public void ActiveIsPouring() { _startTime = Time.time; _isPouring = true; } public void InActiveIsPouring() { _isPouring = false; } private Color MixColorsByTime() { var totalTime = _colorTimes.Values.Sum(); // 혼합된 색상 초기화 (검은색) var mixedColor = Color.black; // 색상 혼합 foreach (var element in _colorTimes) { var color = element.Key; var time = element.Value; var ratio = time / totalTime; mixedColor += color * ratio; } mixedColor.a = 1f; return mixedColor; } } }