This commit is contained in:
CortexCore
2024-03-31 23:31:00 +08:00
parent e179d2eb53
commit b7b89ee71a
641 changed files with 31286 additions and 22134 deletions

View File

@@ -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);
}
}
}

View 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()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2048d435d8387842b5b0c9bf5498a1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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,

View File

@@ -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)

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6cb5fe341e4445841875655ee334f8fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -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);
}
}