using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Linq; using Cysharp.Threading.Tasks; using UnityEngine.Jobs; using UnityEngine.Pool; namespace BITKit.Sensors { public class RangeSensor : Sensor { [Header(Constant.Header.Settings)] public float radius; public int fov; public bool requireSight; [Header(Constant.Header.Settings)] public LayerMask blockLayer; [Header(Constant.Header.InternalVariables)] private FrameUpdate frameUpdater; private readonly Collider[] colliders = new Collider[32]; private RaycastHit[] hits; public override IEnumerable Get() => detected; private void Update() { if (autoUpdate) { Execute().Forget(); } } public override UniTask Execute() { if (frameUpdater.Allow is false) return UniTask.CompletedTask; var location = new Location(transform); var length = Physics.OverlapSphereNonAlloc(location, radius, colliders, detectLayer); var list = new List(); list.AddRange(from x in colliders.Take(length) where IsValid(x) select x.transform); detected = list.ToArray(); list.Clear(); // detected = colliders // .Take(length) // .Select(x => x.transform) // .ToArray(); return UniTask.CompletedTask; } public override bool IsValid(Collider _collider) { switch (_collider) { case var _ when ignoreColliders.Contains(_collider): return false; case var _ when fov > 0 && CheckFov(ref _collider) is false: case var _ when requireSight && CheckSight(ref _collider) is false: return false; default: return true; } } public override float GetDistance() => radius; private bool CheckFov(ref Collider _collider) { var _dir = _collider.transform.position - transform.position; if (_dir.sqrMagnitude <= 0) return false; var dir = Quaternion.LookRotation(_dir); return Vector3.Dot(transform.forward, _dir) > 0 && fov > Quaternion.Angle(transform.rotation, dir); } private bool CheckSight(ref Collider _collider) { if (!requireSight) return false; var transform1 = _collider.transform; var position = transform1.position; var location = new Location(transform); var length = Physics.RaycastNonAlloc( location.position, position - location, hits, Vector3.Distance(location, position), blockLayer ); if (length > 0) { if (hits[0].collider == _collider) { return true; } } else return true; return false; } } }