using System; using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Events; using UnityEngine.UIElements; #if UNITY_EDITOR using UnityEditor; using UnityEditor.UIElements; #endif namespace BITKit.Sensors { public class TriggerSensor : MonoBehaviour, ISensor { [Header(Constant.Header.Settings)] [SerializeField] private List ignores = new(); [SerializeField] private Optional detectedLayer; [SerializeField] private bool allowStatic; [SerializeField] private bool useRigidbody; [Header(Constant.Header.Events)] public UnityEvent onDetected = new(); public UnityEvent onLost = new(); [Header(Constant.Header.InternalVariables)] // ReSharper disable once FieldCanBeMadeReadOnly.Local private List detected = new(); private readonly Queue triggerEnterQueue=new(); private readonly Queue triggerExitQueue=new(); private void OnTriggerEnter(Collider _collider) { triggerEnterQueue.Enqueue(_collider); } private void OnTriggerExit(Collider _collider) { triggerExitQueue.Enqueue(_collider); } private void OnCollisionEnter(Collision collision) { var _collider = collision.collider; if (!IsValid(_collider)) return; detected.Add(_collider); onDetected.Invoke(_collider); } private void OnCollisionStay(Collision collision) { var _collider = collision.collider; if (detected.TryRemove(_collider)) { onLost.Invoke(_collider); } } public IEnumerable Get() => detected.Select(x => x.transform).ToArray(); //public bool IsValid(Collider _collider) => ignores.Contains(_collider.gameObject) is false; public bool IsValid(Collider _collider) { if(allowStatic is false && _collider.gameObject.isStatic) return false; var attachedRigidbody = _collider.attachedRigidbody; var detectedObject = _collider switch { var x when attachedRigidbody is not null && useRigidbody => attachedRigidbody.gameObject, _ => _collider.gameObject, }; if (ignores.Contains(detectedObject)) return false; return !detectedLayer.Allow || detectedLayer.Value.Includes(_collider.gameObject.layer); } public float GetDistance() { throw new NotImplementedException(); } public UniTask Execute() { throw new NotImplementedException(); } private void Update() { while (triggerEnterQueue.TryDequeue(out var _collider)) { if (IsValid(_collider) is false) return; if (triggerExitQueue.Contains(_collider) || detected.Contains(_collider))continue; detected.Add(_collider); } while (triggerExitQueue.TryDequeue(out var _collider)) { if (IsValid(_collider) is false) return; detected.Remove(_collider); } } } #if UNITY_EDITOR [CustomEditor(typeof(Sensor),true)] public class SensorInspector:BITInspector { private VisualElement detectedContainer; public override VisualElement CreateInspectorGUI() { FillDefaultInspector(); detectedContainer = root.Create(); return root; } protected override void OnUpdate() { if (detectedContainer is null) return; detectedContainer.Clear(); foreach (var x in agent.Get()) { ObjectField objectField = new() { objectType = x.GetType(), value = x, }; objectField.SetEnabled(false); detectedContainer.Add(objectField); } } } [CustomEditor(typeof(TriggerSensor),true)] public class TriggerSensorInspector:BITInspector { private VisualElement detectedContainer; public override VisualElement CreateInspectorGUI() { FillDefaultInspector(); detectedContainer = root.Create(); return root; } protected override void OnUpdate() { if (detectedContainer is null) return; detectedContainer.Clear(); foreach (var x in agent.Get()) { ObjectField objectField = new() { objectType = x.GetType(), value = x, }; objectField.SetEnabled(false); detectedContainer.Add(objectField); } } } #endif }