Penjimon
Penjimon

Reputation: 509

Smooth, Fast Coroutines?

So I have a bunch of Coroutines running/working fine in my game.

However, one of them is for a power meter, and here's the issue...

You press the button, the power meter uses the coroutine to start filling up the power meter. (represented by the width of a red panel)

The goal is to make the meter fill up fast enough, as to where you can't just get "full power" every time. However, it also has to be smooth, and look nice.

The problem I'm facing is that my coroutine is maxed out on speed, and can't go any faster, and the meter is moving too slowly. So to "speed up" the meter, I have to use larger width increasing increments on the red panel.

It works, but, this causes 2 problems.

  1. It doesn't look smooth. (It looks choppy and jittery)
  2. It misses a whole bunch of values/possibilities. (e.g. The bar has to increase by a unit of "50" to make it fast enough to be difficult. But that's dumb, because that makes only 12 possibilities when stopping the meter. And there could be up to 600!)

Has anyone faced this before? If so, what's the best approach to making a fast, but smooth power meter, that can still hit a full range of value possibilities?

Thanks, Ben

Here is my Code:

public static IEnumerator StartPitchMeter(Player.Guy guy, float duration)
{

    var dur = 0.01f;

    do
    {
        yield return new WaitForSeconds(dur);

        PlayerControls.PitchMeter += 50f;

        if (PlayerControls.PitchMeter > 600) PlayerControls.PitchMeter = 0f;

        PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, 50);

    } while (!PlayerControls.stopPitch);

}

Upvotes: 0

Views: 199

Answers (1)

Ruzihm
Ruzihm

Reputation: 20259

If you're using a coroutine to update something for graphical purposes, you want to update on every available render frame (same as how often Update methods are called). So, instead of waiting for a set amount of time to pass, use yield return null and then move the meter according to Time.deltaTime, the time elapsed since the last frame in seconds. In this case, you can multiply Time.deltaTime by how many units per second you would like the meter to fill:

public static IEnumerator StartPitchMeter(Player.Guy guy, float duration)
{

    do
    {
        yield return null;

        // Fill 50 units per second.
        float fillThisFrame = Time.deltaTime * 50f;

        PlayerControls.PitchMeter += fillThisFrame;

        if (PlayerControls.PitchMeter > 600) PlayerControls.PitchMeter = 0f;


        PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, 50);
        // Not sure what the 50 is doing here so it might be this instead:
        // PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, fillThisFrame);

    } while (!PlayerControls.stopPitch);

}

Upvotes: 1

Related Questions