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); } // TODO : 가끔씩 공중에서 멈추는 경우? if (_isAcceleratedFall) { var distance = Vector3.Distance(_startPosition, _endPosition); var acceleration = 2 * distance / (_fallTime * _fallTime); // a = 2d / t^2 var displacement = 0.5f * acceleration * elapsedTime * elapsedTime; var progress = displacement / distance; transform.position = Vector3.Lerp(_startPosition, _endPosition, progress); } else { transform.position = Vector3.Lerp(_startPosition, _endPosition, time); } elapsedTime += Time.deltaTime; yield return null; } transform.position = _endPosition; _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; // } // } // // transform.position = _endPosition; 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(); 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; } } }