CapersProject/Assets/02.Scripts/Prop/Rockfall.cs
NTG_Lenovo 07ae6e86b2 Ver 0.2.3.0 업데이트
+ 맵 클리어 이후 DailyBgm으로 변경
+ ItemDropTableSo 클래스 Editor 처리
+ Rockfall 로직 변경
+ Rockfall, SpikeProjectileParticle2 shadowOnly spriteRenderer 추가
2024-06-25 15:19:16 +09:00

189 lines
6.2 KiB
C#

using System.Collections;
using BlueWater.Audios;
using BlueWater.Interfaces;
using BlueWater.Maps;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace BlueWater
{
public class Rockfall : DamageableProps
{
[Title("컴포넌트")]
[SerializeField, Required]
private SphereCollider _sphereCollider;
[SerializeField, Required]
private GameObject _visualLook;
[SerializeField]
private DecalProjector _indicator;
[Title("표시기 설정")]
[SerializeField]
private bool _isUsingIndicator = true;
[Title("충돌 설정")]
[SerializeField]
private LayerMask _targetLayer;
[SerializeField]
private LayerMask _groundLayer;
[SerializeField, Range(0f, 5f), ShowIf("@_isUsingIndicator")]
private float _indicatorTime = 0.5f;
[SerializeField, Range(0f, 5f)]
private float _fallTime = 0.5f;
[SerializeField, Range(0, 5)]
private int _attackDamage = 1;
[SerializeField]
private bool _isAcceleratedFall = true;
[Title("Ground Crash 설정")]
[SerializeField]
private string _groundCrashSfxName;
[SerializeField]
private ParticleSystem _groundCrashParticle;
private Collider[] _hitColliders;
private RaycastHit _raycastHit;
private Vector3 _startPosition;
private Vector3 _endPosition;
private bool _isAttacked;
// Hashes
private static readonly int _fillHash = Shader.PropertyToID("_Fill");
private IEnumerator Start()
{
_visualLook.SetActive(false);
_sphereCollider.enabled = false;
_startPosition = transform.position;
SpawnLocation = MapManager.Instance.SandMoleMapController.ParticleInstanceLocation;
_hitColliders = new Collider[4];
BasicSetting();
if (!Physics.Raycast(transform.position, Vector3.down, out _raycastHit, 50f, _groundLayer))
{
Debug.LogError("땅을 감지하지 못하는 버그");
yield break;
}
_endPosition = _raycastHit.point;
ShowIndicator();
var elapsedTime = 0f;
while (elapsedTime <= _indicatorTime)
{
var time = elapsedTime / _indicatorTime;
if (_isUsingIndicator && _indicator)
{
var fillValue = Mathf.Lerp(0f, 1f, time);
_indicator.material.SetFloat(_fillHash, fillValue);
}
//transform.position = Vector3.Lerp(_startPosition, _endPosition, time);
elapsedTime += Time.deltaTime;
yield return null;
}
_indicator.material.SetFloat(_fillHash, 1f);
HideIndicator();
_visualLook.SetActive(true);
if (_isAcceleratedFall)
{
var distance = Vector3.Distance(_startPosition, _endPosition);
var acceleration = 2 * distance / (_fallTime * _fallTime); // a = 2d / t^2
elapsedTime = 0f;
while (elapsedTime <= _fallTime)
{
var time = elapsedTime;
var displacement = 0.5f * acceleration * time * time;
var progress = displacement / distance;
transform.position = Vector3.Lerp(_startPosition, _endPosition, progress);
elapsedTime += Time.deltaTime;
yield return null;
}
}
else
{
elapsedTime = 0f;
while (elapsedTime <= _fallTime)
{
var time = elapsedTime / _fallTime;
transform.position = Vector3.Lerp(_startPosition, _endPosition, time);
elapsedTime += Time.deltaTime;
yield return null;
}
}
if (!string.IsNullOrEmpty(_groundCrashSfxName))
{
AudioManager.Instance.PlaySfx(_groundCrashSfxName);
}
if (_groundCrashParticle)
{
if (!SpawnLocation)
{
Debug.LogError("파티클 위치 생성 오류");
yield break;
}
Instantiate(_groundCrashParticle, transform.position, Quaternion.identity, SpawnLocation);
}
var hitCount = Physics.OverlapSphereNonAlloc(_sphereCollider.bounds.center, _sphereCollider.radius,
_hitColliders, _targetLayer, QueryTriggerInteraction.Collide);
for (var i = 0; i < hitCount; i++)
{
var hitCollider = _hitColliders[i];
var iDamageable = hitCollider.GetComponentInParent<IDamageable>();
if (iDamageable == null || !iDamageable.CanDamage()) continue;
iDamageable.TakeDamage(_attackDamage);
_isAttacked = true;
}
if (_isAttacked)
{
Die();
yield break;
}
_sphereCollider.enabled = true;
}
private void BasicSetting()
{
if (!_isUsingIndicator || !_indicator) return;
_indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
_indicator.material = new Material(_indicator.material);
_indicator.material.SetFloat(_fillHash, 0f);
}
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;
}
}
}