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 ConcurrentDictionary Sensors=new(); internal static readonly ConcurrentDictionary LastDetectedTime = new(); private static bool IsDirty; [SerializeField,ReadOnly] private int _position; public static void Register(int id,ISensor sensor) { Sensors.TryAdd(id,sensor); MarkDirty(); } public static void UnRegister(int id) { Sensors.TryRemove(id); MarkDirty(); } public static void MarkDirty() { IsDirty = true; } [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; try { _isBusy = true; if(IsDirty) { _position = 0; IsDirty = false; } if (Sensors.Count is 0) { _isBusy = false; return; } var current = Sensors.ElementAt(_position++).Value; if (current.AutoUpdate) { var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time); await current.Execute(Time.time-currentUpdateTime); LastDetectedTime.AddOrUpdate(current.Id,Time.time,UpdateValueFactory); if (destroyCancellationToken.IsCancellationRequested) { _isBusy = false; return; } } _position %= Sensors.Count; float UpdateValueFactory(int key, float old) => Time.time; } catch (Exception e) { BIT4Log.LogException(e); } _isBusy = false; } } }