using FishNet.Documenting; using System; using UnityEngine; namespace FishNet.Managing.Timing { [APIExclude] public class MovingAverage { #region Public. /// /// Average from samples favoring the most recent sample. /// public float Average { get; private set; } #endregion /// /// Next index to write a sample to. /// private int _writeIndex; /// /// Collected samples. /// private float[] _samples; /// /// Number of samples written. Will be at most samples size. /// private int _writtenSamples; /// /// Samples accumulated over queue. /// private float _sampleAccumulator; public MovingAverage(int sampleSize) { if (sampleSize < 0) sampleSize = 0; else if (sampleSize < 2) NetworkManager.StaticLogWarning("Using a sampleSize of less than 2 will always return the most recent value as Average."); _samples = new float[sampleSize]; } /// /// Computes a new windowed average each time a new sample arrives /// /// public void ComputeAverage(float newSample) { if (_samples.Length <= 1) { Average = newSample; return; } _sampleAccumulator += newSample; _samples[_writeIndex] = newSample; //Increase writeIndex. _writeIndex++; _writtenSamples = Math.Max(_writtenSamples, _writeIndex); if (_writeIndex >= _samples.Length) _writeIndex = 0; Average = _sampleAccumulator / _writtenSamples; /* If samples are full then drop off * the oldest sample. This will always be * the one just after written. The entry isn't * actually removed from the array but will * be overwritten next sample. */ if (_writtenSamples >= _samples.Length) _sampleAccumulator -= _samples[_writeIndex]; } } }