見出し画像

Unity Interval Timer作り方

Unityで筋トレ用、ヨガ用、などのインターバルタイマー
(ワークアウト→休み→ワークアウト→休み)みたいな
感じのtimerを作ったのでその方法を紹介します。

とりあえず以下コード。

GameUI.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;


public class GameUI : MonoBehaviour
{
    public static GameUI instance;
    [SerializeField] public Image CircleImage;
    [SerializeField] private Text TimerText;
    public int Duration { get; private set; }
    public bool IsPaused { get; private set; }
    public int remaingDuration;
    private UnityAction onTimerBeginAction;
    private UnityAction<int> onTimerChangeAction;
    private UnityAction onTimerEndAction;
    private UnityAction<bool> onTimerPauuseAction;


    private void Awake()
    {
        ResetTimer();
    }
    private void ResetTimer()
    {
        TimerText.text = "00:00";
        CircleImage.fillAmount = 0f;

        Duration = remaingDuration = 0;

        onTimerBeginAction = null;
        onTimerChangeAction = null;
        onTimerEndAction = null;
        onTimerPauuseAction = null;

        IsPaused = false;
    }

    public void SetPaused(bool paused)
    {
        IsPaused = paused;

        if (onTimerPauuseAction != null)
            onTimerPauuseAction.Invoke(IsPaused);
    }

    public GameUI SetDuration(int seconds)
    {
        Duration = remaingDuration = seconds;
        return this;
    }
    // ---Events-------

    public GameUI OnBegin(UnityAction action)
    {
        onTimerBeginAction = action;
        return this;
    }
    public GameUI OnChange(UnityAction<int> action)
    {
        onTimerChangeAction = action;
        return this;
        // --add--
    }
    public GameUI OnEnd(UnityAction action)
    {
        onTimerEndAction = action;
        return this;
    }
    public GameUI OnPause(UnityAction<bool> action)
    {
        onTimerPauuseAction = action;
        return this;
    }



    public void Begin()
    {
        if (onTimerBeginAction != null)
            onTimerBeginAction.Invoke();

        StopAllCoroutines();
        StartCoroutine(UpdateTimer());

    }

    private IEnumerator UpdateTimer()
    {
        while (remaingDuration > 0)
        {
            if (!IsPaused)
            {
                if (onTimerChangeAction != null)
                    onTimerChangeAction.Invoke(remaingDuration);

                UpdateUI(remaingDuration);
                PlaySoundEvery(remaingDuration);
                remaingDuration--;
            }

            yield return new WaitForSeconds(1f);
        }
        End();
    }
    private void UpdateUI(int seconds)
    {
        TimerText.text = string.Format("{0:D2}:{1:D2}", seconds / 60, seconds % 60);
        CircleImage.fillAmount = Mathf.InverseLerp(0, Duration, seconds);

    }

    // ---add---
    private void PlaySoundEvery(int seconds)
    {
        GetComponent<AudioSource>().Play();
    }

    public void End()
    {
        if (onTimerEndAction != null)
            onTimerEndAction.Invoke();

        ResetTimer();
    }

    private void OnDestroy()
    {
        StopAllCoroutines();
    }
}

Demo.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Demo : MonoBehaviour
{
    AudioSource audioSource;
    public AudioClip[] se;
    int preSecond;
    int nowSecond;
    int timerPhase = 0;

    public int HiitCycles = 14;
    [SerializeField] GameUI timer1;
    [SerializeField] GameUI timer2;

    public int WtimerSec = 60;
    public int StimerSec = 20;

    public GameUI gameui;
    bool startFlag = false;

    [SerializeField] Button StartButton;
    [SerializeField] Button ResestButton;
    [SerializeField] Button StoptButton;

    // public Color SecColor;
    // public Color WColor;
    [SerializeField] private Text RoutinText;
    public int score = 0;

    // --colorgradient--

    public UIGradient gradient;
    public Color restColor1;
    public Color restColor2;

    public Color workColor1;
    public Color workColor2;



    void Start()
    {
        gameui = GetComponent<GameUI>();
        audioSource = GetComponent<AudioSource>();
        // SecColor.a = 1;
        // WColor.a = 1;
        restColor1.a = 1;
        restColor2.a = 1;
        workColor1.a = 1;
        workColor2.a = 1;

        ResestButton.interactable = false;
        StoptButton.interactable = false;



    }

    public void OnClickStart()
    {
        audioSource.PlayOneShot(se[3]);
        Invoke("Wtimer", 2.5f);
        // Wtimer();
        StartButton.interactable = false;
        StoptButton.interactable = true;
    }

    public void OnClickreset()
    {
        if (!timer1.IsPaused || !timer2.IsPaused)
        {
            startFlag = false;
            timerPhase = 0;
            gameui.remaingDuration = 0;
            score = 0;

            audioSource.PlayOneShot(se[3]);
            Invoke("Wtimer", 2.5f);
        }


    }


    void Update()
    {

        RoutinText.text = score.ToString();

        if (startFlag == true)
        {
            if (!timer1.IsPaused || !timer2.IsPaused)
            {
                ResestButton.interactable = true;
            }
            if (gameui.remaingDuration == 0)
            {

                if (timerPhase % 2 == 0)
                {
                    Wtimer();

                }
                else
                {

                    Stimer();
                }
                if (HiitCycles * 2 == timerPhase)
                {
                    audioSource.PlayOneShot(se[0]);
                    startFlag = false;
                    timerPhase = 0;
                    gameui.remaingDuration = 0;
                    score = 0;
                }
            }



        }

    }

    private void Wtimer()
    {

        if (startFlag == false)
        {
            startFlag = true;

        }
        audioSource.PlayOneShot(se[1]);
        WorkColor();

        timer1
        .SetDuration(WtimerSec)
        .OnBegin(() => Debug.Log("Timmer started"))
        // .OnChange(s => Debug.Log("Timmer changed : " + s))
        .OnEnd(() => Debug.Log("Timmer ended"))
        // .OnPause(IsPaused => Debug.Log("----Paused :" + IsPaused))
        .Begin();

        timerPhase++;
        UpdateText();
    }

    private void Stimer()
    {
        if (HiitCycles * 2 - 1 > timerPhase)
        {
            audioSource.PlayOneShot(se[2]);
        }
        SColor();
        timer2
        .SetDuration(StimerSec)
        .OnBegin(() => Debug.Log("Timmer started"))
        // .OnChange(s => Debug.Log("Timmer changed : " + s))
        .OnEnd(() => Debug.Log("Timmer ended"))
        // .OnPause(IsPaused => Debug.Log("----Paused :" + IsPaused))
        .Begin();

        timerPhase++;
    }

    public void PauseButton()
    {
        ResestButton.interactable = false;


        if (timerPhase % 2 == 0)
        {
            timer1.SetPaused(!timer1.IsPaused);
        }
        else
        {
            timer2.SetPaused(!timer2.IsPaused);
        }

    }

    // ---Color--
    public void SColor()
    {
        // gameui.CircleImage.color = SecColor;
        gradient.m_color1 = restColor1;
        gradient.m_color2 = restColor2;
    }
    public void WorkColor()
    {
        // gameui.CircleImage.color = WColor;
        gradient.m_color1 = workColor1;
        gradient.m_color2 = workColor2;

    }

    // --text--
    private void UpdateText()
    {

        score++;
    }


}

以下、詳しく説明・・・・
完成するとこんな感じ。ワークアウト(設定秒数)→休憩(設定秒数)×セット回数ができるようになる







→グラデーションを設定できる

この記事が気に入ったらサポートをしてみませんか?