using System; using SepCore.Definition; using SepCore.Entity; using UnityEngine; namespace SepCore.Components { public class AbsorbComponent : MonoBehaviour { [SerializeField] private int _maxDetectCount = 64; private Player _player; private Transform _target; private StatComponent _statComponent; private Collider[] _buffer; private StatProperty _absorbRangeStat; private Action _absorbRangeStatCallback; private float AbsorbRangeBase => GameEntry.Luban.Global.DefaultAbsorbRange / 1000f; private float AbsorbSpeed => GameEntry.Luban.Global.AbsorbSpeed / 1000f; private float CollectDistance => GameEntry.Luban.Global.CollectDistance / 1000f; private float AbsorbRange => Mathf.Max(0f, (AbsorbRangeBase + _absorbRangeStat.Value) * _absorbRangeStat.Percent); public void OnInit(Player player, StatComponent statComponent) { _player = player; _target = player.CachedTransform; _statComponent = statComponent; _buffer = new Collider[Mathf.Max(1, _maxDetectCount)]; _absorbRangeStat = _statComponent.GetStat(StatType.AbsorbRange); _absorbRangeStatCallback = (modifier, isApply) => _statComponent.UpdateStat(_absorbRangeStat, modifier, isApply); _statComponent.Subscribe(StatType.AbsorbRange, _absorbRangeStatCallback); } public void OnUpdate(float elapseSeconds, float realElapseSeconds) { if (!_player.Available) return; int hitCount = Physics.OverlapSphereNonAlloc( _target.position, AbsorbRange, _buffer, Constant.Layer.DropLayerMask ); for (int i = 0; i < hitCount; i++) { Collider hit = _buffer[i]; if (hit == null) continue; CoinEntity coin = hit.GetComponent(); if (coin != null && coin.Available) { AbsorbDrop(coin.CachedTransform, elapseSeconds); coin.TryCollect(_player, CollectDistance); continue; } ExpEntity exp = hit.GetComponent(); if (exp != null && exp.Available) { AbsorbDrop(exp.CachedTransform, elapseSeconds); exp.TryCollect(_player, CollectDistance); } } } public void OnReset() { if (_statComponent != null) { _statComponent.Unsubscribe(StatType.AbsorbRange, _absorbRangeStatCallback); _absorbRangeStatCallback = null; } _statComponent = null; _target = null; _player = null; _buffer = null; } private void AbsorbDrop(Transform drop, float deltaTime) { drop.position = Vector3.MoveTowards(drop.position, _target.position, AbsorbSpeed * deltaTime); } } }