123 lines
3.9 KiB
C#
123 lines
3.9 KiB
C#
|
using System.Collections;
|
||
|
using Sirenix.OdinInspector;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Rendering.Universal;
|
||
|
|
||
|
namespace BlueWater
|
||
|
{
|
||
|
public class GateOfSpike : MonoBehaviour
|
||
|
{
|
||
|
[Title("컴포넌트")]
|
||
|
[SerializeField, Required]
|
||
|
private ProjectileController _projectileObject;
|
||
|
|
||
|
[SerializeField, Required]
|
||
|
private Rigidbody _rigidbody;
|
||
|
|
||
|
[SerializeField, Required]
|
||
|
private SphereCollider _sphereCollider;
|
||
|
|
||
|
[SerializeField, Required]
|
||
|
private DecalProjector _indicator;
|
||
|
|
||
|
[Title("표시기 설정")]
|
||
|
[SerializeField]
|
||
|
private bool _isUsingIndicator = true;
|
||
|
|
||
|
[Title("설정")]
|
||
|
[SerializeField]
|
||
|
private float _maxHeight = 10f;
|
||
|
|
||
|
[SerializeField]
|
||
|
private Vector2 _randomDuration = new(1f, 1.5f);
|
||
|
|
||
|
private bool _isInitialized;
|
||
|
private Vector3 _destination;
|
||
|
|
||
|
// Hashes
|
||
|
private static readonly int _fillHash = Shader.PropertyToID("_Fill");
|
||
|
|
||
|
private IEnumerator Start()
|
||
|
{
|
||
|
yield return new WaitUntil(() => _isInitialized);
|
||
|
|
||
|
BasicSetting();
|
||
|
ShowIndicator();
|
||
|
|
||
|
var startPosition = transform.position;
|
||
|
var controlPoint = startPosition + Vector3.up * _maxHeight;
|
||
|
var elapsedTime = 0f;
|
||
|
var duration = Random.Range(_randomDuration.x, _randomDuration.y);
|
||
|
|
||
|
while (elapsedTime < duration)
|
||
|
{
|
||
|
if (!_projectileObject)
|
||
|
{
|
||
|
HideIndicator();
|
||
|
Destroy(gameObject, 3.5f);
|
||
|
yield break;
|
||
|
}
|
||
|
|
||
|
elapsedTime += Time.deltaTime;
|
||
|
var t = elapsedTime / duration;
|
||
|
|
||
|
if (_isUsingIndicator && _indicator)
|
||
|
{
|
||
|
var fillValue = Mathf.Lerp(0f, 1f, t);
|
||
|
if (t == 0f)
|
||
|
{
|
||
|
fillValue = 0f;
|
||
|
}
|
||
|
_indicator.material.SetFloat(_fillHash, fillValue);
|
||
|
}
|
||
|
|
||
|
// 베지어 곡선을 사용하여 위치 계산
|
||
|
var position = Mathf.Pow(1 - t, 2) * startPosition +
|
||
|
2 * (1 - t) * t * controlPoint +
|
||
|
Mathf.Pow(t, 2) * _destination;
|
||
|
|
||
|
_projectileObject.transform.position = position;
|
||
|
yield return null;
|
||
|
}
|
||
|
|
||
|
_indicator.material.SetFloat(_fillHash, 1f);
|
||
|
HideIndicator();
|
||
|
|
||
|
Destroy(gameObject, 3.5f);
|
||
|
}
|
||
|
|
||
|
public void Initialize(Vector3 destination)
|
||
|
{
|
||
|
_destination = destination;
|
||
|
_isInitialized = true;
|
||
|
}
|
||
|
|
||
|
private void BasicSetting()
|
||
|
{
|
||
|
if (!_isUsingIndicator || !_indicator) return;
|
||
|
|
||
|
_indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
|
||
|
_indicator.material = new Material(_indicator.material);
|
||
|
_indicator.material.SetFloat(_fillHash, 0f);
|
||
|
var indicatorScale = _projectileObject.SphereRadius * 2f;
|
||
|
_indicator.transform.localScale = Vector3.one * indicatorScale;
|
||
|
_indicator.transform.position = _destination + Vector3.up * _sphereCollider.radius;
|
||
|
}
|
||
|
|
||
|
private void HideIndicator()
|
||
|
{
|
||
|
if (!_isUsingIndicator || !_indicator) return;
|
||
|
|
||
|
_indicator.enabled = false;
|
||
|
_indicator.material.SetFloat(_fillHash, 0);
|
||
|
}
|
||
|
|
||
|
private void ShowIndicator()
|
||
|
{
|
||
|
if (!_isUsingIndicator || !_indicator) return;
|
||
|
|
||
|
_indicator.material.SetFloat(_fillHash, 0);
|
||
|
_indicator.enabled = true;
|
||
|
}
|
||
|
}
|
||
|
}
|