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();
}
}
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++;
}
}
以下、詳しく説明・・・・
完成するとこんな感じ。ワークアウト(設定秒数)→休憩(設定秒数)×セット回数ができるようになる
→グラデーションを設定できる