1
This commit is contained in:
@@ -17,6 +17,10 @@ namespace BITKit.Sensors
|
||||
/// </summary>
|
||||
public interface ISensor
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动更新
|
||||
/// </summary>
|
||||
bool AutoUpdate => false;
|
||||
/// <summary>
|
||||
/// 是否监测到任何目标
|
||||
/// </summary>
|
||||
@@ -108,5 +112,21 @@ namespace BITKit.Sensors
|
||||
public abstract bool IsValid(Collider _collider);
|
||||
public abstract UniTask Execute();
|
||||
public abstract float GetDistance();
|
||||
|
||||
bool ISensor.AutoUpdate => autoUpdate;
|
||||
|
||||
protected int Id;
|
||||
protected Transform Transform;
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
Transform = transform;
|
||||
SensorQueue.Register(Id=GetInstanceID(),this);
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
SensorQueue.UnRegister(Id);
|
||||
}
|
||||
}
|
||||
}
|
18
Src/Unity/Scripts/Sensor/NewBehaviourScript.cs
Normal file
18
Src/Unity/Scripts/Sensor/NewBehaviourScript.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class NewBehaviourScript : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
11
Src/Unity/Scripts/Sensor/NewBehaviourScript.cs.meta
Normal file
11
Src/Unity/Scripts/Sensor/NewBehaviourScript.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2048d435d8387842b5b0c9bf5498a1f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -35,22 +35,14 @@ namespace BITKit.Sensors
|
||||
}
|
||||
private readonly DoubleBuffer<IEnumerable<Transform>> _detectedDoubleBuffer=new();
|
||||
private IEnumerable<Transform> _detectedBuffer;
|
||||
private void Update()
|
||||
{
|
||||
if (autoUpdate && SensorGlobalSettings.Enabled)
|
||||
{
|
||||
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 length = Physics.OverlapSphereNonAlloc(Transform.position, radius, colliders, detectLayer);
|
||||
Profiler.BeginSample("Filter Detected Colliders");
|
||||
var _newDetected = from x in colliders.Take(length) where IsValid(x) select x.transform;
|
||||
Profiler.EndSample();
|
||||
//detected = _newDetected.ToArray();
|
||||
_detectedDoubleBuffer.Release(_newDetected);
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
@@ -82,7 +74,7 @@ namespace BITKit.Sensors
|
||||
if (!requireSight) return false;
|
||||
var transform1 = _collider.transform;
|
||||
var position = transform1.position;
|
||||
var location = new Location(transform);
|
||||
var location = new Location(Transform);
|
||||
var length = Physics.RaycastNonAlloc(
|
||||
location.position,
|
||||
position - location,
|
||||
|
@@ -9,14 +9,29 @@ namespace BITKit.Sensors
|
||||
public class RaySensor : Sensor
|
||||
{
|
||||
[Header(Constant.Header.Settings)]
|
||||
[SerializeField] private float radius = 0.16f;
|
||||
public float distance;
|
||||
public override IEnumerable<Transform> Get() => detected;
|
||||
private readonly RaycastHit[] raycasts = new RaycastHit[16];
|
||||
public override UniTask Execute()
|
||||
{
|
||||
var _transform = transform;
|
||||
var ray = new Ray(_transform.position,_transform.forward);
|
||||
var size = Physics.RaycastNonAlloc(ray, raycasts, distance, detectLayer);
|
||||
var forward = _transform.forward;
|
||||
var position = _transform.position;
|
||||
|
||||
var size = 0;
|
||||
if (radius is not 0)
|
||||
{
|
||||
size = Physics.CapsuleCastNonAlloc(position, position + forward * distance, radius, forward,
|
||||
raycasts
|
||||
, distance, detectLayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ray = new Ray(_transform.position,_transform.forward);
|
||||
size = Physics.RaycastNonAlloc(ray, raycasts, distance, detectLayer);
|
||||
}
|
||||
|
||||
detected = raycasts
|
||||
.Take(size)
|
||||
.Select(x => x.collider)
|
||||
|
63
Src/Unity/Scripts/Sensor/SensorQueue.cs
Normal file
63
Src/Unity/Scripts/Sensor/SensorQueue.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
public class SensorQueue : MonoBehaviour
|
||||
{
|
||||
internal static readonly Dictionary<int,ISensor> Sensors=new();
|
||||
private static bool IsDirty;
|
||||
|
||||
[SerializeField,ReadOnly] private int _position;
|
||||
|
||||
private static int[] _keys;
|
||||
|
||||
public static void Register(int id,ISensor sensor)
|
||||
{
|
||||
Sensors.Add(id,sensor);
|
||||
MarkDirty();
|
||||
}
|
||||
public static void UnRegister(int id)
|
||||
{
|
||||
Sensors.Remove(id);
|
||||
MarkDirty();
|
||||
}
|
||||
public static void MarkDirty()
|
||||
{
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
[SerializeField] private MonoBehaviour[] sensors;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (SensorGlobalSettings.Enabled is false) return;
|
||||
if(IsDirty)
|
||||
{
|
||||
_position = 0;
|
||||
_keys = Sensors.Where(IsEnabled).Select(x=>x.Key).ToArray();
|
||||
IsDirty = false;
|
||||
sensors = Sensors.Values.Where(IsEnabled).OfType<MonoBehaviour>().ToArray();
|
||||
}
|
||||
|
||||
if(Sensors.Count is 0) return;
|
||||
|
||||
Sensors.ElementAt(_position++).Value.Execute().Forget();
|
||||
|
||||
_position %= Sensors.Count;
|
||||
}
|
||||
private bool IsEnabled(ISensor sensor)
|
||||
{
|
||||
return sensor.AutoUpdate;
|
||||
}
|
||||
private bool IsEnabled(KeyValuePair<int,ISensor> pair)
|
||||
{
|
||||
return pair.Value.AutoUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
11
Src/Unity/Scripts/Sensor/SensorQueue.cs.meta
Normal file
11
Src/Unity/Scripts/Sensor/SensorQueue.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cb5fe341e4445841875655ee334f8fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,14 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.Accessibility;
|
||||
using UnityEngine.Profiling;
|
||||
using UnityEngine.UIElements;
|
||||
// ReSharper disable PossibleMultipleEnumeration
|
||||
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
@@ -24,21 +28,27 @@ namespace BITKit.Sensors
|
||||
[SerializeField] private bool autoUpdate;
|
||||
[SerializeField] private Optional<string[]> ignoreTags;
|
||||
[SerializeField] private Optional<IntervalUpdate> optionalRetargetInterval;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 主传感器
|
||||
/// </summary>
|
||||
[Header(nameof(Sensor))]
|
||||
[SerializeField,SerializeReference,SubclassSelector] private ISensor sensor;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
[Header(Constant.Header.Debug)]
|
||||
[SerializeField] private Transform sensorTransform;
|
||||
#endif
|
||||
[SerializeReference, ReadOnly] private int updateCount;
|
||||
|
||||
public IEnumerable<Transform> Get() =>CurrentTarget is not null ? new[] { CurrentTarget }:Enumerable.Empty<Transform>();
|
||||
|
||||
bool ISensor.AutoUpdate => autoUpdate;
|
||||
|
||||
internal StringBuilder reportBuilder;
|
||||
internal DoubleBuffer<string> report=new();
|
||||
|
||||
public bool IsValid(Collider _collider)
|
||||
{
|
||||
if (!_collider) return false;
|
||||
if (ignoreTags.Allow)
|
||||
{
|
||||
if (_collider.TryGetComponent<ITag>(out var iTags))
|
||||
@@ -58,40 +68,92 @@ namespace BITKit.Sensors
|
||||
public float GetDistance() => sensor.GetDistance();
|
||||
public Transform CurrentTarget { get; private set; }
|
||||
private IEnumerable<Transform> detected = ArraySegment<Transform>.Empty;
|
||||
private Vector3 _currentPosition;
|
||||
private int Id;
|
||||
|
||||
private CancellationTokenSource timeoutCancellationTokenSource=new();
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SensorQueue.Register(Id=GetInstanceID(),this);
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
SensorQueue.UnRegister(Id);
|
||||
}
|
||||
public async UniTask Execute()
|
||||
{
|
||||
var currentPosition = transform.position;
|
||||
await sensor.Execute();
|
||||
Profiler.BeginSample("Release Detected Buffer");
|
||||
var newDetected = sensor.Get();
|
||||
Profiler.EndSample();
|
||||
// ReSharper disable once PossibleMultipleEnumeration
|
||||
if (newDetected.Contains(CurrentTarget))
|
||||
try
|
||||
{
|
||||
if (optionalRetargetInterval.Allow && optionalRetargetInterval.Value.AllowUpdate)
|
||||
_currentPosition = transform.position;
|
||||
updateCount++;
|
||||
timeoutCancellationTokenSource?.Cancel();
|
||||
timeoutCancellationTokenSource = new CancellationTokenSource();
|
||||
await sensor.Execute();
|
||||
|
||||
reportBuilder?.AppendLine($"-----BEGIN------{updateCount}");
|
||||
|
||||
Profiler.BeginSample("Release Detected Buffer");
|
||||
var newDetected = sensor.Get();
|
||||
|
||||
if (reportBuilder is not null)
|
||||
{
|
||||
|
||||
reportBuilder.AppendLine($"Detected:{newDetected.Count()}");
|
||||
foreach (var x in newDetected)
|
||||
{
|
||||
reportBuilder.AppendLine(x.name);
|
||||
}
|
||||
reportBuilder.AppendLine();
|
||||
}
|
||||
Profiler.EndSample();
|
||||
// ReSharper disable once PossibleMultipleEnumeration
|
||||
if (newDetected.Contains(CurrentTarget))
|
||||
{
|
||||
if (optionalRetargetInterval.Allow && optionalRetargetInterval.Value.AllowUpdate)
|
||||
{
|
||||
reportBuilder?.AppendLine("Retarget Interval Catch,Search New Target");
|
||||
}
|
||||
else
|
||||
{
|
||||
reportBuilder?.AppendLine("Current Target Detected,Keep Target");
|
||||
return;
|
||||
}
|
||||
}
|
||||
Profiler.BeginSample("Filter Detected");
|
||||
|
||||
foreach (var x in newDetected.OrderBy(KeySelector))
|
||||
{
|
||||
if(IsValid(x.GetComponent<Collider>()) is false)continue;
|
||||
CurrentTarget = x;
|
||||
reportBuilder?.AppendLine($"New Target:{x.name},Is oder by distance");
|
||||
break;
|
||||
}
|
||||
Profiler.EndSample();
|
||||
|
||||
reportBuilder?.AppendLine($"-----Complete------{updateCount}");
|
||||
|
||||
if(reportBuilder is not null)
|
||||
{
|
||||
report.Release(reportBuilder.ToString());
|
||||
reportBuilder.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
report.Clear();
|
||||
}
|
||||
}
|
||||
Profiler.BeginSample("Filter Detected");
|
||||
// ReSharper disable once PossibleMultipleEnumeration
|
||||
CurrentTarget = newDetected
|
||||
.Where(_transform => IsValid(_transform.GetComponent<Collider>()))
|
||||
.OrderBy(_transform => Vector3.Distance(currentPosition, _transform.position))
|
||||
.FirstOrDefault();
|
||||
Profiler.EndSample();
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void Update()
|
||||
private float KeySelector(Transform x)
|
||||
{
|
||||
if(autoUpdate && SensorGlobalSettings.Enabled)Execute().Forget();
|
||||
var distance = Vector3.Distance(_currentPosition, x.position);
|
||||
reportBuilder?.AppendLine($"Distance:{distance}@{x.name}");
|
||||
return distance;
|
||||
}
|
||||
|
||||
void IAction.Execute()
|
||||
{
|
||||
Execute().Forget();
|
||||
@@ -101,8 +163,8 @@ namespace BITKit.Sensors
|
||||
{
|
||||
try
|
||||
{
|
||||
if (CurrentTarget is null || sensorTransform is null) return;
|
||||
Gizmos.DrawLine(sensorTransform.position,CurrentTarget.position);
|
||||
if (!CurrentTarget) return;
|
||||
Gizmos.DrawLine(transform.position,CurrentTarget.position);
|
||||
}
|
||||
catch (UnassignedReferenceException)
|
||||
{
|
||||
@@ -116,6 +178,7 @@ namespace BITKit.Sensors
|
||||
public class SmartTargetSensorInspector:BITInspector<SmartTargetSensor>
|
||||
{
|
||||
private ObjectField _objectField;
|
||||
private Label _reportLabel;
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
FillDefaultInspector();
|
||||
@@ -128,15 +191,36 @@ namespace BITKit.Sensors
|
||||
|
||||
_objectField.SetEnabled(false);
|
||||
|
||||
_reportLabel = root.Create<Label>();
|
||||
|
||||
_reportLabel.text = "Waiting agent report";
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override void OnEnabled()
|
||||
{
|
||||
base.OnEnabled();
|
||||
agent.reportBuilder = new();
|
||||
}
|
||||
|
||||
protected override void OnDisabled()
|
||||
{
|
||||
base.OnDisabled();
|
||||
agent.reportBuilder = null;
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (_objectField is not null)
|
||||
{
|
||||
_objectField.value = agent.CurrentTarget;
|
||||
}
|
||||
|
||||
if (agent.reportBuilder is not null && _reportLabel is not null && agent.report.TryGetRelease(out var value))
|
||||
{
|
||||
_reportLabel.text = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -28,20 +28,21 @@ namespace BITKit.Sensors
|
||||
[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 readonly Queue<Collider> triggerEnterQueue = new();
|
||||
private readonly Queue<Collider> triggerExitQueue = new();
|
||||
private bool diagnosisNextFrame;
|
||||
|
||||
|
||||
private void OnTriggerEnter(Collider _collider)
|
||||
{
|
||||
triggerEnterQueue.Enqueue(_collider);
|
||||
if(immediately)Rebuild();
|
||||
if (immediately) Rebuild();
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider _collider)
|
||||
{
|
||||
triggerExitQueue.Enqueue(_collider);
|
||||
if(immediately)Rebuild();
|
||||
if (immediately) Rebuild();
|
||||
}
|
||||
|
||||
private void OnCollisionEnter(Collision collision)
|
||||
@@ -63,24 +64,17 @@ namespace BITKit.Sensors
|
||||
|
||||
public IEnumerable<Transform> Get()
|
||||
{
|
||||
if(BITAppForUnity.IsPlaying is false)return ArraySegment<Transform>.Empty;
|
||||
try
|
||||
{
|
||||
return detected.Select(x => x.transform).ToArray();
|
||||
return detected.Select(x => x.transform).ToArray();
|
||||
}
|
||||
catch (MissingReferenceException)
|
||||
{
|
||||
List<Transform> list = new();
|
||||
foreach (var x in detected)
|
||||
{
|
||||
try
|
||||
{
|
||||
list.Add(x.transform);
|
||||
}
|
||||
catch (MissingReferenceException){}
|
||||
}
|
||||
return list.ToArray();
|
||||
detected = detected.Where(x => x).ToList();
|
||||
}
|
||||
}
|
||||
return detected.Select(x => x.transform).ToArray();
|
||||
}
|
||||
|
||||
//public bool IsValid(Collider _collider) => ignores.Contains(_collider.gameObject) is false;
|
||||
public bool IsValid(Collider _collider)
|
||||
@@ -101,10 +95,8 @@ namespace BITKit.Sensors
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public UniTask Execute()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public UniTask Execute()=>
|
||||
UniTask.CompletedTask;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
@@ -177,16 +169,17 @@ namespace BITKit.Sensors
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (!agent || detectedContainer is null) return;
|
||||
if (BITAppForUnity.IsPlaying is false) return;
|
||||
detectedContainer.Clear();
|
||||
foreach (var x in agent.Get())
|
||||
foreach (var x in agent.detected)
|
||||
{
|
||||
|
||||
ObjectField objectField = new()
|
||||
{
|
||||
objectType = x.GetType(),
|
||||
value = x,
|
||||
};
|
||||
objectField.SetEnabled(false);
|
||||
objectField.style.opacity = 1;
|
||||
detectedContainer.Add(objectField);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user