2024-08-14 10:52:35 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
2024-08-13 10:13:09 +00:00
|
|
|
using Sirenix.OdinInspector;
|
|
|
|
using UnityEngine;
|
2024-08-14 10:52:35 +00:00
|
|
|
using UnityEngine.Pool;
|
2024-08-13 10:13:09 +00:00
|
|
|
|
|
|
|
namespace BlueWater
|
|
|
|
{
|
|
|
|
public class LiquidController : MonoBehaviour
|
|
|
|
{
|
2024-08-22 10:39:15 +00:00
|
|
|
#region Variables
|
|
|
|
|
|
|
|
[Title("컴포넌트")]
|
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
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
[SerializeField]
|
|
|
|
private Collider2D _reachedCollider;
|
2024-08-13 10:13:09 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
[Title("스폰 데이터")]
|
2024-08-13 10:13:09 +00:00
|
|
|
[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]
|
2024-08-22 10:39:15 +00:00
|
|
|
private Vector3 _pushDirection;
|
2024-08-14 10:52:35 +00:00
|
|
|
|
|
|
|
[SerializeField]
|
2024-08-22 10:39:15 +00:00
|
|
|
private float _pushPower;
|
|
|
|
|
|
|
|
[Title("액체")]
|
|
|
|
[SerializeField, Required, Tooltip("액체 프리팹")]
|
|
|
|
private Liquid _liquidObject;
|
|
|
|
|
|
|
|
[SerializeField, Tooltip("떨어지는 액체의 색상")]
|
|
|
|
private Color _liquidColor = new(1f, 0.8431373f, 0f, 1f);
|
2024-08-19 08:14:35 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
[SerializeField, Tooltip("초당 생성되는 액체 수(ml)")]
|
|
|
|
private int _liquidsPerSecond = 80;
|
2024-08-19 08:14:35 +00:00
|
|
|
|
|
|
|
[SerializeField]
|
2024-08-22 10:39:15 +00:00
|
|
|
private int _maxLiquidCount = 400;
|
2024-08-19 10:56:07 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
[SerializeField, Range(0f, 1f), Tooltip("목표 색상으로 변경되는데 걸리는 시간")]
|
2024-08-19 10:56:07 +00:00
|
|
|
private float _colorLerpSpeed = 0.5f;
|
2024-08-22 10:39:15 +00:00
|
|
|
|
|
|
|
[SerializeField, Range(1f, 5f), Tooltip("목표 색상 * 밝기")]
|
|
|
|
private float _colorIntensity = 2f;
|
|
|
|
|
|
|
|
[Title("오브젝트 풀링")]
|
|
|
|
[SerializeField, Tooltip("오브젝트 풀링 최대 개수")]
|
|
|
|
private int _objectPoolCount = 1000;
|
2024-08-14 10:52:35 +00:00
|
|
|
|
|
|
|
private IObjectPool<Liquid> _objectPool;
|
|
|
|
private List<Liquid> _activeLiquids = new();
|
2024-08-22 10:39:15 +00:00
|
|
|
private Dictionary<Color, int> _colorCounts = new();
|
2024-08-19 08:14:35 +00:00
|
|
|
private Material _instanceMaterial;
|
2024-08-22 10:39:15 +00:00
|
|
|
|
2024-08-14 10:52:35 +00:00
|
|
|
private bool _isPouring;
|
|
|
|
private float _startTime = float.PositiveInfinity;
|
2024-08-22 10:39:15 +00:00
|
|
|
private int _instanceLiquidCount;
|
|
|
|
private float _currentLiquidAmount;
|
|
|
|
private float _liquidReachedTime;
|
2024-08-19 08:14:35 +00:00
|
|
|
private float _timeInterval;
|
2024-08-19 10:56:07 +00:00
|
|
|
private Color _currentMixedColor = Color.black;
|
|
|
|
private Color _targetColor;
|
2024-08-22 10:39:15 +00:00
|
|
|
|
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-22 10:39:15 +00:00
|
|
|
private static readonly int _renderTextureColorHash = Shader.PropertyToID("_Color");
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
// Unity events
|
|
|
|
#region Unity events
|
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;
|
|
|
|
_instanceMaterial.SetFloat(_liquidAmountHash, 0f);
|
2024-08-19 03:15:31 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 10:13:09 +00:00
|
|
|
private void Update()
|
|
|
|
{
|
2024-08-14 10:52:35 +00:00
|
|
|
if (_isPouring)
|
2024-08-13 10:13:09 +00:00
|
|
|
{
|
2024-08-22 10:39:15 +00:00
|
|
|
if (_instanceLiquidCount >= _maxLiquidCount)
|
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();
|
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
if (!_colorCounts.TryAdd(_liquidColor, 1))
|
2024-08-19 08:14:35 +00:00
|
|
|
{
|
2024-08-22 10:39:15 +00:00
|
|
|
_colorCounts[_liquidColor] += 1;
|
2024-08-19 08:14:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_startTime = Time.time;
|
2024-08-14 10:52:35 +00:00
|
|
|
}
|
2024-08-13 10:13:09 +00:00
|
|
|
}
|
2024-08-19 10:56:07 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
if (_liquidReachedTime + _colorLerpSpeed >= Time.time)
|
2024-08-19 10:56:07 +00:00
|
|
|
{
|
|
|
|
_currentMixedColor = Color.Lerp(_currentMixedColor, _targetColor, _colorLerpSpeed * Time.deltaTime);
|
2024-08-22 10:39:15 +00:00
|
|
|
_instanceMaterial.SetColor(_liquidColorHash, _currentMixedColor * _colorIntensity);
|
2024-08-19 10:56:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
// Initialize methods
|
|
|
|
#region Initialize methods
|
|
|
|
|
2024-08-19 10:56:07 +00:00
|
|
|
public void Initialize()
|
|
|
|
{
|
2024-08-22 10:39:15 +00:00
|
|
|
_instanceLiquidCount = 0;
|
|
|
|
_currentLiquidAmount = 0f;
|
2024-08-19 10:56:07 +00:00
|
|
|
_currentMixedColor = _liquidColor;
|
2024-08-22 10:39:15 +00:00
|
|
|
_instanceMaterial.SetColor(_liquidColorHash, _currentMixedColor * _colorIntensity);
|
2024-08-13 10:13:09 +00:00
|
|
|
}
|
2024-08-14 10:52:35 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
// Object pooling system
|
|
|
|
#region Object pooling system
|
|
|
|
|
2024-08-14 10:52:35 +00:00
|
|
|
private Liquid CreateObject()
|
|
|
|
{
|
|
|
|
var instance = Instantiate(_liquidObject, _spawnTransform.position, Quaternion.identity, _spawnLocation);
|
|
|
|
instance.SetManagedPool(_objectPool);
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnGetObject(Liquid liquid)
|
|
|
|
{
|
|
|
|
liquid.transform.position = _spawnTransform.position;
|
|
|
|
liquid.transform.rotation = Quaternion.identity;
|
2024-08-22 10:39:15 +00:00
|
|
|
liquid.gameObject.SetActive(true);
|
|
|
|
_instanceLiquidCount++;
|
|
|
|
liquid.Initialize(this, _reachedCollider, _liquidColor, _pushDirection.normalized * _pushPower);
|
|
|
|
if (_renderTexture && _renderTexture.material.GetColor(_renderTextureColorHash) != _liquidColor)
|
2024-08-19 08:14:35 +00:00
|
|
|
{
|
2024-08-22 10:39:15 +00:00
|
|
|
_renderTexture.material.SetColor(_renderTextureColorHash, _liquidColor);
|
2024-08-19 08:14:35 +00:00
|
|
|
}
|
2024-08-14 10:52:35 +00:00
|
|
|
_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
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
#endregion
|
2024-08-19 08:14:35 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
// Custom methods
|
|
|
|
#region Custom methods
|
2024-08-19 08:14:35 +00:00
|
|
|
|
2024-08-14 10:52:35 +00:00
|
|
|
[Button("기본 색상")]
|
2024-08-22 10:39:15 +00:00
|
|
|
private void DefaultColor() => _liquidColor = new Color(1f, 0.8431373f, 0f, 1f);
|
2024-08-14 10:52:35 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
/// <summary>
|
|
|
|
/// 술 제조 과정 초기화 함수
|
|
|
|
/// </summary>
|
2024-08-14 10:52:35 +00:00
|
|
|
public void ReleaseAllObject()
|
|
|
|
{
|
2024-08-22 10:39:15 +00:00
|
|
|
// 리스트 삭제는 뒤에서부터 해야 오류가 없음
|
2024-08-14 10:52:35 +00:00
|
|
|
for (var i = _activeLiquids.Count - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
_activeLiquids[i].Destroy();
|
|
|
|
}
|
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
_colorCounts.Clear();
|
|
|
|
_instanceLiquidCount = 0;
|
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-22 10:39:15 +00:00
|
|
|
/// <summary>
|
|
|
|
/// 사용된 색상의 비율에 맞게 색을 혼합시키는 함수
|
|
|
|
/// </summary>
|
|
|
|
private Color MixColorsByTime()
|
|
|
|
{
|
|
|
|
var totalCounts = _colorCounts.Values.Sum();
|
|
|
|
|
|
|
|
var mixedColor = Color.black;
|
|
|
|
|
|
|
|
foreach (var element in _colorCounts)
|
|
|
|
{
|
|
|
|
var color = element.Key;
|
|
|
|
var count = element.Value;
|
|
|
|
var ratio = count / (float)totalCounts;
|
|
|
|
|
|
|
|
mixedColor += color * ratio;
|
|
|
|
}
|
|
|
|
|
|
|
|
mixedColor.a = 1f;
|
|
|
|
|
|
|
|
return mixedColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 액체가 특정 오브젝트에 충돌했을 때, 실행해야하는 과정
|
|
|
|
/// </summary>
|
2024-08-19 08:14:35 +00:00
|
|
|
public void OnLiquidReached()
|
2024-08-14 10:52:35 +00:00
|
|
|
{
|
2024-08-22 10:39:15 +00:00
|
|
|
_liquidReachedTime = Time.time;
|
|
|
|
_currentLiquidAmount++;
|
|
|
|
var liquidAmount = Mathf.Clamp(_currentLiquidAmount / _maxLiquidCount, 0f, 1f);
|
2024-08-19 08:14:35 +00:00
|
|
|
_instanceMaterial.SetFloat(_liquidAmountHash, liquidAmount);
|
2024-08-19 10:56:07 +00:00
|
|
|
_targetColor = MixColorsByTime();
|
2024-08-19 08:14:35 +00:00
|
|
|
|
2024-08-22 10:39:15 +00:00
|
|
|
if (liquidAmount >= 1f)
|
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
|
|
|
}
|
|
|
|
}
|
2024-08-22 10:39:15 +00:00
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
2024-08-13 10:13:09 +00:00
|
|
|
}
|
|
|
|
}
|