Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity3D - Find average value of float that changes each second

Tags:

c#

average

I'm calculating speed and it works fine. But how I can find average value of speed variable? Speed value changes approximately once per second(when GPS value updates). I need to display user average speed when he(she) presses 'finish' button

Thanks for any help

Here is my sample code:

void Update()
{
    timer += Time.deltaTime;

    if (lonA != Input.location.lastData.longitude || latA != Input.location.lastData.latitude)
    {
        CalculateDistances(lonA, latA, Input.location.lastData.longitude, Input.location.lastData.latitude);  // last distance and overall distanceS            
        lonA = Input.location.lastData.longitude;
        latA = Input.location.lastData.latitude;

        lastTime = timer;
        timer = 0;

        speed0 = speed;

        CalculateSpeed();
    }
}

public static float Radians(float x)
{
    return x * Mathf.PI / 180;
}

public void CalculateDistances(float firstLon, float firstLat, float secondLon, float secondLat)
{
    float dlon = Radians(secondLon - firstLon);
    float dlat = Radians(secondLat - firstLat);

    float distance = Mathf.Pow(Mathf.Sin(dlat / 2), 2) + Mathf.Cos(Radians(firstLat)) * Mathf.Cos(Radians(secondLat)) * Mathf.Pow(Mathf.Sin(dlon / 2), 2);

    float c = 2 * Mathf.Atan2(Mathf.Sqrt(distance), Mathf.Sqrt(1 - distance));

    lastDistance = 6371 * c * 1000;
}

void CalculateSpeed()
{
    speed = lastDistance / lastTime * 3.6f;

    speedText.text = Mathf.RoundToInt(speed).ToString();
}
like image 954
Nurlan Shukurov Avatar asked Jul 15 '26 22:07

Nurlan Shukurov


2 Answers

CyrillFind's answer is close but will return incorrect averages if you are taking into account the total data set. Let's say for a second that the user only runs the game for 3 seconds and logs three values of (10, 20 ,30) mph. If you calculate the average and add to it "as you go" then the average of this would come out as 22.5. If the full set of data was taken into account then it would average to 20.

This happens for the "as you go" method because each time you only take into account the last average and the next value; thus you only divide by the amount of data you have for that calculation (2) which forgets about all previous pieces of data.

If you want a fully accurate average then you should store the speed values that are collected every second in a List<> and then calculate the average at the end by iterating over this list<> once the user pushed "Finished".

An example of how to do this:

List<float> speeds = new List<float>()
void CalculateSpeed()
{
    speed = lastDistance / lastTime * 3.6f;

    speedText.text = Mathf.RoundToInt(speed).ToString();

    speeds.Add(speed);
}

void float returnAverage() //call when Finished
{
    float averageTotal;
    float finalTotal;

    for(int i = 0; i < speeds.Count; i++)
    {
         averageTotal += speeds[i]
    }

    finalTotal = averageTotal / speeds.Count;
    speeds.Clear() // so as the list is free for the next time
    return finalTotal;
}

Even better and simpler than that, if you know the distance and the time that the user has tracked while running then just use the formula speed = distance/time.

like image 68
Danny Herbert Avatar answered Jul 18 '26 13:07

Danny Herbert


If I understand well, you should just store an average speed like this:

private int averageSpeed = 0;

When the user starts his trip, something like:

public void Begin() {
  averageSpeed = 0;
}

When you calculate your speed :

void CalculateSpeed()
{
    speed = lastDistance / lastTime * 3.6f;

    speedText.text = Mathf.RoundToInt(speed).ToString();

    averageSpeed = (averageSpeed + speed) / 2
}

And when the user presses "Finish"

public void Finish() {
    averageSpeedText.text = Mathf.RoundToInt(averageSpeed).ToString();
}
like image 32
CyrilFind Avatar answered Jul 18 '26 12:07

CyrilFind