BITFALL/Assets/BITKit/Unity/Scripts/Sensor/Smart/SmartTargetSensor.cs

144 lines
3.4 KiB
C#
Raw Normal View History

2023-08-12 01:43:24 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
#endif
using UnityEngine;
2023-11-15 23:54:54 +08:00
using UnityEngine.Profiling;
2023-08-12 01:43:24 +08:00
using UnityEngine.UIElements;
namespace BITKit.Sensors
{
/// <summary>
/// 智能目标传感器,根据条件,智能选择目标
/// </summary>
public class SmartTargetSensor :MonoBehaviour,ISensor,IAction
{
/// <summary>
/// 自动更新
/// </summary>
[Header(Constant.Header.Settings)]
[SerializeField] private bool autoUpdate;
2023-11-15 23:54:54 +08:00
[SerializeField] private Optional<string[]> ignoreTags;
[SerializeField] private Optional<IntervalUpdate> optionalRetargetInterval;
2023-08-12 01:43:24 +08:00
/// <summary>
/// 主传感器
/// </summary>
[Header(nameof(Sensor))]
[SerializeField,SerializeReference,SubclassSelector] private ISensor sensor;
#if UNITY_EDITOR
[Header(Constant.Header.Debug)]
[SerializeField] private Transform sensorTransform;
#endif
public IEnumerable<Transform> Get() =>CurrentTarget is not null ? new[] { CurrentTarget }:Enumerable.Empty<Transform>();
2023-11-15 23:54:54 +08:00
public bool IsValid(Collider _collider)
{
if (ignoreTags.Allow)
{
if (_collider.TryGetComponent<ITag>(out var iTags))
{
var tags = iTags.GetTags();
foreach (var x in ignoreTags.Value)
{
if (tags.Contains(x))
{
return false;
}
}
}
}
return true;
}
2023-08-12 01:43:24 +08:00
public float GetDistance() => sensor.GetDistance();
public Transform CurrentTarget { get; private set; }
2023-11-15 23:54:54 +08:00
private IEnumerable<Transform> detected = ArraySegment<Transform>.Empty;
2023-08-12 01:43:24 +08:00
public async UniTask Execute()
{
2023-11-30 00:23:23 +08:00
var currentPosition = transform.position;
2023-08-12 01:43:24 +08:00
await sensor.Execute();
2023-11-15 23:54:54 +08:00
Profiler.BeginSample("Release Detected Buffer");
var newDetected = sensor.Get();
Profiler.EndSample();
// ReSharper disable once PossibleMultipleEnumeration
if (newDetected.Contains(CurrentTarget))
2023-08-12 01:43:24 +08:00
{
2023-11-15 23:54:54 +08:00
if (optionalRetargetInterval.Allow && optionalRetargetInterval.Value.AllowUpdate)
2023-08-12 01:43:24 +08:00
{
2023-11-15 23:54:54 +08:00
2023-08-12 01:43:24 +08:00
}
else
{
2023-11-15 23:54:54 +08:00
return;
2023-08-12 01:43:24 +08:00
}
}
2023-11-15 23:54:54 +08:00
Profiler.BeginSample("Filter Detected");
// ReSharper disable once PossibleMultipleEnumeration
CurrentTarget = newDetected
2023-08-12 01:43:24 +08:00
.Where(_transform => IsValid(_transform.GetComponent<Collider>()))
2023-11-30 00:23:23 +08:00
.OrderBy(_transform => Vector3.Distance(currentPosition, _transform.position))
2023-08-12 01:43:24 +08:00
.FirstOrDefault();
2023-11-15 23:54:54 +08:00
Profiler.EndSample();
2023-08-12 01:43:24 +08:00
}
private void Update()
{
2023-11-15 23:54:54 +08:00
if(autoUpdate && SensorGlobalSettings.Enabled)Execute().Forget();
2023-08-12 01:43:24 +08:00
}
void IAction.Execute()
{
Execute().Forget();
}
#if UNITY_EDITOR
private void OnDrawGizmosSelected()
{
2023-10-20 19:31:12 +08:00
try
{
if (CurrentTarget is null || sensorTransform is null) return;
Gizmos.DrawLine(sensorTransform.position,CurrentTarget.position);
}
catch (UnassignedReferenceException)
{
}
2023-08-12 01:43:24 +08:00
}
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(SmartTargetSensor))]
public class SmartTargetSensorInspector:BITInspector<SmartTargetSensor>
{
private ObjectField _objectField;
public override VisualElement CreateInspectorGUI()
{
FillDefaultInspector();
CreateSubTitle("Editor Debug Field");
_objectField = root.Create<ObjectField>();
_objectField.objectType = typeof(Transform);
_objectField.SetEnabled(false);
return root;
}
protected override void OnUpdate()
{
if (_objectField is not null)
{
_objectField.value = agent.CurrentTarget;
}
}
}
#endif
}