using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; using UnityEngine; namespace BITKit.Sensors { public class SensorQueue : MonoBehaviour { internal static readonly Dictionary Sensors=new(); internal static readonly ConcurrentDictionary LastDetectedTime = 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; [SerializeReference,SubclassSelector] private ITicker ticker; private bool _isBusy; private void Start() { ticker.Add(OnTick); destroyCancellationToken.Register(Dispose); } private void Dispose() { ticker.Remove(OnTick); } private async void OnTick(float obj) { if (_isBusy) return; if (SensorGlobalSettings.Enabled is false) return; _isBusy = true; if(IsDirty) { _position = 0; _keys = Sensors.Where(IsEnabled).Select(x=>x.Key).ToArray(); IsDirty = false; sensors = Sensors.Values.Where(IsEnabled).OfType().ToArray(); } if (Sensors.Count is 0) { _isBusy = false; return; } var current = Sensors.ElementAt(_position++).Value; 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; } _position %= Sensors.Count; _isBusy = false; } private bool IsEnabled(ISensor sensor) { return sensor.AutoUpdate; } private bool IsEnabled(KeyValuePair pair) { return pair.Value.AutoUpdate; } } }