using System; 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] private Rigidbody _rigidbody; [SerializeField, Required] private SphereCollider _sphereCollider; [SerializeField] private DecalProjector _indicator; [Title("표시기 설정")] [SerializeField] private bool _isUsingIndicator = true; [Title("충돌 설정")] [SerializeField] private LayerMask _targetLayer; [SerializeField] private LayerMask _groundLayer; [SerializeField, Range(0f, 1f)] private float _checkDistance = 0.1f; [SerializeField, Range(0, 5)] private int _attackDamage = 1; [Title("Ground Crash 설정")] [SerializeField] private string _groundCrashSfxName; [SerializeField] private ParticleSystem _groundCrashParticle; private Collider[] _hitColliders = new Collider[4]; private RaycastHit _raycastHit; private float _startDistance = float.PositiveInfinity; private bool _isGrounded; private bool _isAttacked; // Hashes private static readonly int _fillHash = Shader.PropertyToID("_Fill"); private void OnDrawGizmos() { Debug.DrawRay(transform.position, Vector3.down * _checkDistance, _isGrounded ? Color.blue : Color.red); } private void Start() { _sphereCollider.enabled = false; SpawnLocation = MapManager.Instance.SandMoleMapController.ParticleInstantiateLocation; if (!Physics.Raycast(transform.position, Vector3.down, out _raycastHit, 10f, _groundLayer)) { Debug.LogError("땅을 감지하지 못하는 버그"); return; } BasicSetting(); ShowIndicator(); _startDistance = _raycastHit.distance; } private void Update() { if (!Physics.Raycast(transform.position, Vector3.down, out _raycastHit, 10f, _groundLayer)) { Debug.LogError("땅을 감지하지 못하는 버그"); return; } _isGrounded = _raycastHit.distance <= _checkDistance; if (!_isGrounded) { if (_isUsingIndicator && _indicator) { var fillValue = Mathf.Lerp(1f, 0f, _raycastHit.distance / _startDistance); _indicator.material.SetFloat(_fillHash, fillValue); } } else if (_isGrounded && !_isAttacked) { _indicator.material.SetFloat(_fillHash, 1f); HideIndicator(); if (_rigidbody) { _rigidbody.isKinematic = true; } _sphereCollider.enabled = true; if (!string.IsNullOrEmpty(_groundCrashSfxName)) { AudioManager.Instance.PlaySfx(_groundCrashSfxName); } if (_groundCrashParticle && SpawnLocation) { 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); Die(); } _isAttacked = 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; } } }