Home > database >  How do I make timer change a sprite every second without using code that's redundant?
How do I make timer change a sprite every second without using code that's redundant?

Time:05-20

I'm not entirely sure how to phrase question so sorry if this is confusing. Anyways for context I'm making a sort of minesweeper type of game in unity and one of the things the original game had was a timer. enter image description here

CodePudding user response:

Coroutines are perfect for this. Try this code here:

public Image image;
public Sprite[] sprites;
private bool isStop = true;

private void Start()
{
    isStop = false;
    StartCoroutine(Timer());
}

private IEnumerator Timer()
{
    while (!isStop)
    {
        for (int i = 0; i < sprites.Length; i  )
        {
            if (isStop) break;
            image.sprite = sprites[i];
            yield return new WaitForSeconds(1f);
        }
    }
}

CodePudding user response:

You can convert float to int

int spriteIndex = (int)Math.Round(timer);

And used spriteIndex as index to array sprites. Or... if you need used different time interval for every sprite, you can make special struct for this animation. For example:

[Serializable]
public struct SpriteFrame
{
    public Sprite FrameSprite;
    public float TimeToShow;
}

public class SpriteAnimationComponent : MonoBehaviour
{
    public Image ScoreCount; 
    public List<SpriteFrame> Frames = new List<SpriteFrame>();
    private int _currentFrame = 0;
    private float _currentPlayAnimationTime = 0f;
    
    private bool IsPlay => _currentFrame < Frames.Count;

    public void Start()
    {
        UpdateFrame();
    }
    
    public void Update()
    {
        if(!IsPlay)
            return;

        _currentPlayAnimationTime  = Time.deltaTime;
        if(NeedShowNextFrame())
            ShowNextFrame();
    }

    private bool NeedShowNextFrame()
        => Frames[_currentFrame].TimeToShow < _currentPlayAnimationTime;
    
    private void ShowNextFrame()
    {
        _currentPlayAnimationTime -= Frames[_currentFrame].TimeToShow;
        _currentFrame  ;
        if(IsPlay)
        {
            UpdateFrame();
        }
    }

    private void UpdateFrame()
    {
        ScoreCount.sprite = Frames[_currentFrame].FrameSprite;
    }
}

You need used SerializableAttribute ([Serializable]) on SpriteFrame for show struct in Unity Inspector. In current code animation show once, but you can make it loop. For loop animation just add _currentFrame %= Frames.Count after _currentFrame

CodePudding user response:

I'm assuming you have 10 sprites for you numbers 0-9.

numberSprite[0] would hold the sprite for "0", numberSprite[1] would hole "1", etc.

Let's say the timer is at 319.8f seconds on the back end. You would want 3 sprites to display: 3, 1, 9.

To do this, you'll need to break your timer value and sprite into the hundredths, tenths, and seconds individually. You could do this:

    int timerInt = (int)Mathf.floor(timer); //Get the int value of the timer

    int hundredth = (timerInt/100) % 10; // (319/100) => 3 ... (3 % 10) => 3
    scoreCountHundredths.sprite = numberSprite[hundredth];

    int tenth = (timerInt /10) % 10; //(319/10) => 31 ... (31 % 10) => 1
    scoreCountTenths.sprite = numberSprite[tenth];

    int second = timerInt % 10; // (319 % 10) => 9
    scoreCountSeconds.sprite = numberSprite[second];

With the above code, your timer should correctly update to any number between 000-999 requiring only 10 sprites uploaded. Additionally, it will automatically loop if your timer goes above 999 due to the modulo (%) logic.

Warning. Coroutines or InvokeRepeating may be a trap here: Coroutines can be used to track the time between updating the sprites, but you'll likely be wanting to tie this display directly to the in-game time. relying on coroutines to update the sprite de-couples the in-game timer from the display, as they do not have built-in catchup behaviour. If your frames are slightly delayed or lag at all, you run the risk of the time running slower when using coroutines or InvokeRepeating.

  • Related