This commit is contained in:
CortexCore
2024-04-22 03:48:37 +08:00
parent 0362b2c606
commit c1f51826b3
35 changed files with 556 additions and 270 deletions

View File

@@ -5,7 +5,6 @@ using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Pool;
using System.Linq;
using UnityEditor.Search;
namespace BITKit.Sensors
{
@@ -19,6 +18,8 @@ namespace BITKit.Sensors
[SerializeField] private bool autoUpdate;
[SerializeField]private float radius;
private readonly CacheList<Transform> cache = new();
private readonly CacheList<AudioSensorService.AudioSensorData> data = new();
public AudioSensorService.AudioSensorData[] Noises => data.ValueArray;
private void OnEnable()
{
Id = GetInstanceID();
@@ -32,14 +33,19 @@ namespace BITKit.Sensors
{
var position = transform.position;
cache.Clear();
data.Clear();
foreach (var x in AudioSensorService.QuadtreeRoot.Find(new Bounds(position, Vector3.one * radius)))
{
var distance = Vector3.Distance(position, x.Position);
if(distance>radius) continue;
cache.Add(x.Transform);
var distance = Vector3.Distance(position, x.Position);
if (distance > radius) continue;
if (x.Transform)
cache.Add(x.Transform);
data.Add(x);
}
return UniTask.CompletedTask;
}
public HashSet<int> Ignores { get; } = new();
public int Id { get; set; }
public IEnumerable<Transform> Get() => cache.ValueArray;
public bool IsValid(Collider _collider) => false;

View File

@@ -10,6 +10,7 @@ using UnityEngine.Pool;
namespace BITKit.Sensors
{
public struct ClassicNoise{}
public class AudioSensorService : MonoBehaviour
{
public class AudioSensorData:IItem<AudioSensorData,Node<AudioSensorData>>
@@ -20,6 +21,7 @@ namespace BITKit.Sensors
public Transform Transform;
public Bounds Bounds;
public ITag Tag;
public object NoiseType;
public Bounds GetBounds() => Bounds;
public Node<AudioSensorData> ParentNode { get; set; }
public void QuadTree_Root_Initialized(IQuadtreeRoot<AudioSensorData, Node<AudioSensorData>> root){}
@@ -29,20 +31,25 @@ namespace BITKit.Sensors
private static Pool<AudioSensorData> pool = new(()=>new(), x=>{}, 1000);
private static int count;
public static async void MakeNoise(Vector3 position,Transform transform)
public static async void MakeNoise(Vector3 position, Transform transform, float radius = 1,
object noiseType = null)
{
var data = pool.Take();
data.Id = count++;
data.Position = position;
data.Transform = transform;
data.Bounds = new Bounds(position, Vector3.one *1);
data.Tag = transform.GetComponent<ITag>();
data.Bounds = new Bounds(position, Vector3.one * 1);
if (transform)
data.Tag = transform.GetComponent<ITag>();
data.Radius = radius;
QuadtreeRoot.Insert(data);
await UniTask.Delay(3000);
if (disposed) return;
QuadtreeRoot.Remove(data);
pool.Return(data);
}
private static bool disposed;
[SerializeReference, SubclassSelector] private ITicker ticker;
private void Start()

View File

@@ -47,6 +47,7 @@ namespace BITKit.Sensors
/// </summary>
/// <returns></returns>
UniTask Execute(float delta);
HashSet<int> Ignores{ get; }
}
[Serializable]
@@ -74,6 +75,7 @@ namespace BITKit.Sensors
{
return _sensorImplementation.Execute(delta);
}
public HashSet<int> Ignores => _sensorImplementation.Ignores;
}
[System.Serializable]
public class SensorMonoProxy:ISensor
@@ -101,6 +103,7 @@ namespace BITKit.Sensors
{
return _sensorImplementation.Execute(delta);
}
public HashSet<int> Ignores => _sensorImplementation.Ignores;
}
public abstract class Sensor : MonoBehaviour, ISensor
{
@@ -109,13 +112,11 @@ namespace BITKit.Sensors
public bool autoUpdate;
[Header(Constant.Header.Gameobjects)]
public Collider[] ignoreColliders;
[Header(Constant.Header.InternalVariables)]
[SerializeField,ReadOnly]
public Transform[] detected = Array.Empty<Transform>();
public abstract IEnumerable<Transform> Get();
public abstract bool IsValid(Collider _collider);
public abstract float GetDistance();
public virtual UniTask Execute(float delta)=>UniTask.CompletedTask;
public HashSet<int> Ignores { get; } = new();
public int Id { get; private set; }
bool ISensor.AutoUpdate => autoUpdate;

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using Cysharp.Threading.Tasks;
using Unity.Mathematics;
using UnityEngine.Jobs;
using UnityEngine.Pool;
using UnityEngine.Profiling;
@@ -13,19 +14,23 @@ namespace BITKit.Sensors
{
public class RangeSensor : Sensor
{
[Header(Constant.Header.Settings)] public float radius;
public int fov;
public bool requireSight;
[Header(Constant.Header.Settings)] public LayerMask blockLayer;
[Header(Constant.Header.Debug)] [Header(Constant.Header.InternalVariables)]
private FrameUpdate frameUpdater;
[Header(Constant.Header.Settings)]
[SerializeField] private float radius;
[SerializeField] private float detectedHeightWeight=0.5f;
[Header(Constant.Header.Optional)]
[SerializeField] private Optional<int> fov;
[SerializeField] private Optional<LayerMask> requireSight;
[SerializeField] private Optional<float> perceptionRadius;
public float DetectedHeightWeight
{
get=>detectedHeightWeight;
set=>detectedHeightWeight=value;
}
private readonly Collider[] colliders = new Collider[32];
private RaycastHit[] hits = new RaycastHit[32];
private readonly HashSet<int> tempHashSet = new();
private readonly RaycastHit[] hits = new RaycastHit[32];
private float _delta;
public override IEnumerable<Transform> Get()
{
if (!_detectedDoubleBuffer.TryGetRelease(out var newRelease)) return _detectedBuffer;
@@ -40,7 +45,7 @@ namespace BITKit.Sensors
public override UniTask Execute(float delta)
{
tempHashSet.Clear();
_delta = delta;
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;
@@ -53,10 +58,21 @@ namespace BITKit.Sensors
{
switch (_collider)
{
case var _ when Ignores.Contains(_collider.GetInstanceID()):
case var _ when ignoreColliders.Contains(_collider):
return false;
case var _ when fov > 0 && CheckFov(ref _collider) is false:
case var _ when requireSight && CheckSight(ref _collider) is false:
}
if (perceptionRadius.Allow)
{
var distance = Vector3.Distance(Transform.position, _collider.bounds.center);
if(distance<=perceptionRadius.Value) return !requireSight.Allow || CheckSight(ref _collider);
}
switch (_collider)
{
case var _ when fov.Allow && CheckFov(ref _collider) is false:
case var _ when requireSight.Allow && CheckSight(ref _collider) is false:
return false;
default:
return true;
@@ -75,23 +91,21 @@ namespace BITKit.Sensors
private bool CheckSight(ref Collider _collider)
{
if (!requireSight) return false;
var position = _collider.bounds.center;
//是检测bounds的顶部
position.y += _collider.bounds.extents.y;
var location = new Location(Transform);
var bounds = _collider.bounds;
var position = bounds.center;
position.y += bounds.size.y * detectedHeightWeight /2;
var selfPosition = Transform.position;
var length = Physics.RaycastNonAlloc(
location.position,
position - location,
selfPosition,
position - selfPosition,
hits,
Vector3.Distance(location, position),
blockLayer
Vector3.Distance(selfPosition, position),
requireSight.Value
);
switch (length)
{
case 0:
Debug.DrawLine(location, position, Color.green, 1);
Debug.DrawLine(selfPosition, position, Color.green,_delta);
return true;
case 1:
return hits[0].collider == _collider;
@@ -107,7 +121,8 @@ namespace BITKit.Sensors
var result = ignoreColliders.Contains(x.collider) is false && x.collider != collider1;
if (result)
{
Debug.DrawLine(location, x.point, Color.red, 1);
Debug.DrawLine(selfPosition, x.point, Color.yellow,_delta);
Debug.DrawLine(selfPosition, position, Color.red,_delta);
}
return result;
}

View File

@@ -2,7 +2,9 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cysharp.Threading.Tasks;
using Unity.Mathematics;
using UnityEngine;
namespace BITKit.Sensors
{
@@ -11,8 +13,11 @@ namespace BITKit.Sensors
[Header(Constant.Header.Settings)]
[SerializeField] private float radius = 0.16f;
public float distance;
public override IEnumerable<Transform> Get() => detected;
public override IEnumerable<Transform> Get() => detected.ValueArray;
private readonly RaycastHit[] raycasts = new RaycastHit[16];
private readonly Queue<(Vector3,Vector3)> _drawGizmosQueue = new();
private readonly CacheList<Transform> detected = new();
public override UniTask Execute(float delta)
{
var _transform = transform;
@@ -28,25 +33,43 @@ namespace BITKit.Sensors
}
else
{
var ray = new Ray(_transform.position,_transform.forward);
var ray = new Ray(_transform.position, _transform.forward);
size = Physics.RaycastNonAlloc(ray, raycasts, distance, detectLayer);
}
detected = raycasts
.Take(size)
.Select(x => x.collider)
.Where(IsValid)
.Select(x=>x.transform)
.ToArray();
//var reportBuilder = new StringBuilder();
detected.Clear();
foreach (var hit in raycasts
.Take(size)
.Where(IsValid)
.OrderBy(ByDistance))
{
detected.Add(hit.transform);
}
//Debug.Log(reportBuilder);
return UniTask.CompletedTask;
float ByDistance(RaycastHit arg)
{
var x = Vector3.Distance(arg.point, position);
//_drawGizmosQueue.Enqueue(new(arg.collider.bounds.center, arg.point));
//reportBuilder.AppendLine($"Name:{arg.collider.name},Distance:{x}");
return x;
}
}
public bool IsValid(RaycastHit hit) => IsValid(hit.collider);
public override bool IsValid(Collider _collider) => ignoreColliders.Contains(_collider) is false;
public override float GetDistance() => distance;
private void Update()
private void OnDrawGizmosSelected()
{
if (autoUpdate)
while (_drawGizmosQueue.TryDequeue(out var p))
{
Execute(Time.deltaTime).Forget();
var (closePoint, point) = p;
Gizmos.DrawWireCube(point,Vector3.one*0.01f);
Gizmos.DrawLine(closePoint,point);
}
}
}

View File

@@ -16,8 +16,6 @@ namespace BITKit.Sensors
[SerializeField,ReadOnly] private int _position;
private static int[] _keys;
public static void Register(int id,ISensor sensor)
{
Sensors.Add(id,sensor);
@@ -33,7 +31,6 @@ namespace BITKit.Sensors
IsDirty = true;
}
[SerializeField] private MonoBehaviour[] sensors;
[SerializeReference,SubclassSelector] private ITicker ticker;
private bool _isBusy;
@@ -56,9 +53,7 @@ namespace BITKit.Sensors
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)
@@ -68,26 +63,22 @@ namespace BITKit.Sensors
}
var current = Sensors.ElementAt(_position++).Value;
var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time);
if (current.AutoUpdate)
{
var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time);
await current.Execute(Time.time-currentUpdateTime);
float UpdateValueFactory(int key, float old) => Time.time;
LastDetectedTime.AddOrUpdate(current.Id,Time.time,UpdateValueFactory);
if (destroyCancellationToken.IsCancellationRequested) {
_isBusy = false;
return;
if (destroyCancellationToken.IsCancellationRequested) {
_isBusy = false;
return;
}
}
_position %= Sensors.Count;
_isBusy = false;
}
private bool IsEnabled(ISensor sensor)
{
return sensor.AutoUpdate;
}
private bool IsEnabled(KeyValuePair<int,ISensor> pair)
{
return pair.Value.AutoUpdate;
return;
float UpdateValueFactory(int key, float old) => Time.time;
}
}

View File

@@ -30,6 +30,7 @@ namespace BITKit.Sensors
[SerializeField] private AudioSensor audioSensor;
public int Id { get; set; }
private readonly CacheList<Transform> _detected=new();
public HashSet<int> Ignores { get; } = new();
private void OnEnable()
{
Id = GetInstanceID();

View File

@@ -28,6 +28,7 @@ namespace BITKit.Sensors
[Header(Constant.Header.InternalVariables)]
// ReSharper disable once FieldCanBeMadeReadOnly.Local
private List<Collider> detected = new();
public HashSet<int> Ignores { get; } = new();
private readonly Queue<Collider> triggerEnterQueue = new();
private readonly Queue<Collider> triggerExitQueue = new();
@@ -171,7 +172,7 @@ namespace BITKit.Sensors
if (!agent || detectedContainer is null) return;
if (BITAppForUnity.IsPlaying is false) return;
detectedContainer.Clear();
foreach (var x in agent.detected)
foreach (var x in agent.Get())
{
ObjectField objectField = new()
{