BITKit/Packages/Runtime~/Unity/Scripts/Sensor/TriggerSensor.cs

160 lines
5.1 KiB
C#

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<GameObject> ignores = new();
[SerializeField] private Optional<LayerMask> detectedLayer;
[SerializeField] private bool allowStatic;
[SerializeField] private bool useRigidbody;
[Header(Constant.Header.Events)] public UnityEvent<Collider> onDetected = new();
public UnityEvent<Collider> onLost = new();
[Header(Constant.Header.InternalVariables)]
// ReSharper disable once FieldCanBeMadeReadOnly.Local
private List<Collider> detected = new();
private readonly Queue<Collider> triggerEnterQueue=new();
private readonly Queue<Collider> 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<Transform> 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<Sensor>
{
private VisualElement detectedContainer;
public override VisualElement CreateInspectorGUI()
{
FillDefaultInspector();
detectedContainer = root.Create<VisualElement>();
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<TriggerSensor>
{
private VisualElement detectedContainer;
public override VisualElement CreateInspectorGUI()
{
FillDefaultInspector();
detectedContainer = root.Create<VisualElement>();
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
}