CapersProject/Assets/02.Scripts/LiquidController.cs

223 lines
7.0 KiB
C#
Raw Normal View History

2024-08-14 10:52:35 +00:00
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
2024-08-14 10:52:35 +00:00
using UnityEngine.Pool;
namespace BlueWater
{
public class LiquidController : MonoBehaviour
{
2024-08-19 08:14:35 +00:00
[SerializeField]
private Renderer _renderTexture;
2024-08-14 10:52:35 +00:00
[SerializeField]
2024-08-19 03:15:31 +00:00
private Renderer _liquidRenderer;
2024-08-14 10:52:35 +00:00
[SerializeField, Required]
2024-08-14 10:52:35 +00:00
private Liquid _liquidObject;
[SerializeField, Required]
private Transform _spawnTransform;
2024-08-14 10:52:35 +00:00
[SerializeField]
private Transform _spawnLocation;
2024-08-19 08:14:35 +00:00
[SerializeField]
private Collider2D _reachedCollider;
2024-08-14 10:52:35 +00:00
[SerializeField]
private int _objectPoolCount = 1000;
[SerializeField]
private Color _liquidColor = new(0f, 0.7294118f, 1f, 1f);
2024-08-19 08:14:35 +00:00
[SerializeField, Tooltip("1초에 차는 %")]
private float _pouringRate = 20f;
[SerializeField]
private int _liquidsPerSecond = 100;
[SerializeField, Range(0f, 100f)]
private float _currentLiquidAmount;
2024-08-19 10:56:07 +00:00
[SerializeField, Range(0f, 1f)]
private float _colorLerpSpeed = 0.5f;
2024-08-14 10:52:35 +00:00
private IObjectPool<Liquid> _objectPool;
private List<Liquid> _activeLiquids = new();
private Dictionary<Color, float> _colorTimes = new();
2024-08-19 08:14:35 +00:00
private Material _instanceMaterial;
2024-08-14 10:52:35 +00:00
private bool _isPouring;
private float _startTime = float.PositiveInfinity;
2024-08-19 10:56:07 +00:00
private float _endTime = float.PositiveInfinity;
2024-08-19 08:14:35 +00:00
private float _timeInterval;
private float _liquidPerObject;
2024-08-19 10:56:07 +00:00
private Color _currentMixedColor = Color.black;
private Color _targetColor;
2024-08-14 10:52:35 +00:00
// Hashes
2024-08-19 08:14:35 +00:00
private static readonly int _liquidAmountHash = Shader.PropertyToID("_LiquidAmount");
private static readonly int _liquidColorHash = Shader.PropertyToID("_LiquidColor");
2024-08-14 10:52:35 +00:00
private void Awake()
{
_objectPool = new ObjectPool<Liquid>(CreateObject, OnGetObject, OnReleaseObject, OnDestroyObject, maxSize: _objectPoolCount);
}
2024-08-19 03:15:31 +00:00
private void Start()
{
2024-08-19 08:14:35 +00:00
_instanceMaterial = Instantiate(_liquidRenderer.material);
_liquidRenderer.material = _instanceMaterial;
_timeInterval = 1f / _liquidsPerSecond;
_liquidPerObject = _pouringRate / _liquidsPerSecond;
_instanceMaterial.SetFloat(_liquidAmountHash, 0f);
2024-08-19 03:15:31 +00:00
}
private void Update()
{
2024-08-14 10:52:35 +00:00
if (_isPouring)
{
2024-08-19 08:14:35 +00:00
if (_currentLiquidAmount >= 100f)
2024-08-14 10:52:35 +00:00
{
2024-08-19 08:14:35 +00:00
InActiveIsPouring();
return;
2024-08-14 10:52:35 +00:00
}
2024-08-19 08:14:35 +00:00
if (Time.time - _startTime >= _timeInterval)
2024-08-14 10:52:35 +00:00
{
2024-08-19 08:14:35 +00:00
_objectPool.Get();
if (_colorTimes.ContainsKey(_liquidColor))
{
_colorTimes[_liquidColor] += _timeInterval;
}
else
{
_colorTimes[_liquidColor] = _timeInterval;
}
_startTime = Time.time;
2024-08-14 10:52:35 +00:00
}
}
2024-08-19 10:56:07 +00:00
if (_endTime + _colorLerpSpeed >= Time.time)
{
_currentMixedColor = Color.Lerp(_currentMixedColor, _targetColor, _colorLerpSpeed * Time.deltaTime);
_instanceMaterial.SetColor(_liquidColorHash, _currentMixedColor);
}
}
public void Initialize()
{
_currentMixedColor = _liquidColor;
_instanceMaterial.SetColor(_liquidColorHash, _currentMixedColor);
}
2024-08-14 10:52:35 +00:00
private Liquid CreateObject()
{
var instance = Instantiate(_liquidObject, _spawnTransform.position, Quaternion.identity, _spawnLocation);
instance.SetManagedPool(_objectPool);
2024-08-19 08:14:35 +00:00
instance.Initialize(this, _reachedCollider, _liquidColor);
2024-08-19 10:56:07 +00:00
if (_renderTexture && _renderTexture.material.GetColor("_Color") != _liquidColor)
{
_renderTexture.material.SetColor("_Color", _liquidColor);
}
2024-08-14 10:52:35 +00:00
return instance;
}
private void OnGetObject(Liquid liquid)
{
liquid.transform.position = _spawnTransform.position;
liquid.transform.rotation = Quaternion.identity;
2024-08-19 08:14:35 +00:00
liquid.Initialize(this, _reachedCollider, _liquidColor);
if (_renderTexture && _renderTexture.material.GetColor("_Color") != _liquidColor)
{
_renderTexture.material.SetColor("_Color", _liquidColor);
}
2024-08-14 10:52:35 +00:00
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);
}
2024-08-19 08:14:35 +00:00
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;
}
2024-08-14 10:52:35 +00:00
[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();
2024-08-19 08:14:35 +00:00
_currentLiquidAmount = 0f;
_instanceMaterial.SetFloat(_liquidAmountHash, 0f);
2024-08-14 10:52:35 +00:00
}
public void ActiveIsPouring()
{
_startTime = Time.time;
_isPouring = true;
}
public void InActiveIsPouring()
{
_isPouring = false;
}
2024-08-19 08:14:35 +00:00
public void OnLiquidReached()
2024-08-14 10:52:35 +00:00
{
2024-08-19 10:56:07 +00:00
_endTime = Time.time;
2024-08-19 08:14:35 +00:00
// 컵에 채워진 액체의 양을 증가시킴
_currentLiquidAmount += _liquidPerObject;
_currentLiquidAmount = Mathf.Clamp(_currentLiquidAmount, 0f, 100f);
var liquidAmount = _currentLiquidAmount * 0.01f;
_instanceMaterial.SetFloat(_liquidAmountHash, liquidAmount);
2024-08-19 10:56:07 +00:00
_targetColor = MixColorsByTime();
//_instanceMaterial.SetColor(_liquidColorHash, MixColorsByTime());
2024-08-19 08:14:35 +00:00
// 액체가 100%에 도달하면 pouring을 멈춤
if (_currentLiquidAmount >= 100f)
2024-08-14 10:52:35 +00:00
{
2024-08-19 08:14:35 +00:00
InActiveIsPouring();
2024-08-14 10:52:35 +00:00
}
}
}
}