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
|
|
|
|
}
|