![見出し画像](https://assets.st-note.com/production/uploads/images/124617491/rectangle_large_type_2_dadb4971ad873b7487372574bde3e663.png?width=1200)
NDI™で送信するRTAイベントタイマーをUnityで作る #08 並走タイマー編
並走タイマー、並走 RTA 時に各走者のタイムを記録し、画面に出力する部分を作ります
仕様
走者の表示部分をほぼボタンにし、押した瞬間に現在のタイマーの値を黄色く表示する。もう一度押すと表示を消して、さらに押しなおすともう一回値を取得して表示する
右下に入力欄を設けて、入力した数字をそのまま表示することで修正を可能にする
Runner01 Object の作成
走者 1 用のオブジェクトを作成する。4 人並走まで対応できるように、01~04 まで用意する
数字の配置はカウントダウンタイマーと同じなので、そちらから流用する
Runner01Main.cs
ボタンが押されるたびに on_off フラグを入れ替えて、フラグが true のときはタイムを取得して表示する
入力欄の編集が終わったら、入力された内容を数字に変換して表示する。数字が8文字に満たない場合は 0 を埋めて、コロンが入るはずの 3 文字目、6 文字目は無視する。0~9 以外の文字が入っていた場合は例外となりデバッグログを出力しておく
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class Runner01Main : MonoBehaviour
{
[SerializeField] CountUpMain countup;
[SerializeField] TMP_InputField input;
[SerializeField] Image hour1_image;
[SerializeField] Image hour2_image;
[SerializeField] Image colon1_image;
[SerializeField] Image minute1_image;
[SerializeField] Image minute2_image;
[SerializeField] Image colon2_image;
[SerializeField] Image second1_image;
[SerializeField] Image second2_image;
[SerializeField] Sprite[] number = new Sprite[10];
public bool on_off;
// Start is called before the first frame update
void Start()
{
SetDisplay(false);
on_off = false;
}
// Update is called once per frame
void Update()
{
}
// このボタンがクリックされた時の処理。public にしておかないとインスペクターから見えない
public void OnClick()
{
if (countup == null)
{
return;
}
if (on_off == false)
{
SetTime(countup.now_time + countup.offset_time);
on_off = true;
}
else
{
SetDisplay(false);
on_off = false;
}
}
public void EndEdit()
{
string time_string = input.text.PadLeft(8, '0');
float time = 0.0f;
float num;
try
{
num = float.Parse(time_string.Substring(0, 1));
time += num * 36000;
}
catch (FormatException e)
{
Debug.Log(e.Message);
}
try
{
num = float.Parse(time_string.Substring(1, 1));
time += num * 3600;
}
catch (FormatException e)
{
Debug.Log(e.Message);
}
try
{
num = float.Parse(time_string.Substring(3, 1));
time += num * 600;
}
catch (FormatException e)
{
Debug.Log(e.Message);
}
try
{
num = float.Parse(time_string.Substring(4, 1));
time += num * 60;
}
catch (FormatException e)
{
Debug.Log(e.Message);
}
try
{
num = float.Parse(time_string.Substring(6, 1));
time += num * 10;
}
catch (FormatException e)
{
Debug.Log(e.Message);
}
try
{
num = float.Parse(time_string.Substring(7, 1));
time += num;
}
catch (FormatException e)
{
Debug.Log(e.Message);
}
SetTime(time);
}
void SetTime(float ftime)
{
if (ftime < 0.0f)
{
ftime = 0.0f;
}
ftime = ftime * 10;
int itime = Mathf.FloorToInt(ftime);
int hour = itime / 36000;
int hour1 = hour / 10;
int hour2 = hour - hour1 * 10;
hour1_image.sprite = number[hour1];
hour2_image.sprite = number[hour2];
itime = itime - hour * 36000;
int minute = itime / 600;
int minute1 = minute / 10;
int minute2 = minute - minute1 * 10;
minute1_image.sprite = number[minute1];
minute2_image.sprite = number[minute2];
itime = itime - minute * 600;
int second = itime / 10;
int second1 = second / 10;
int second2 = second - second1 * 10;
second1_image.sprite = number[second1];
second2_image.sprite = number[second2];
int decimal1 = itime - second * 10;
// 表示非表示を設定する
if (hour1 > 0)
{
hour1_image.enabled = true;
hour2_image.enabled = true;
colon1_image.enabled = true;
minute1_image.enabled = true;
minute2_image.enabled = true;
colon2_image.enabled = true;
second1_image.enabled = true;
second2_image.enabled = true;
return;
}
else
{
hour1_image.enabled = false;
}
if (hour2 > 0)
{
hour2_image.enabled = true;
colon1_image.enabled = true;
minute1_image.enabled = true;
minute2_image.enabled = true;
colon2_image.enabled = true;
second1_image.enabled = true;
second2_image.enabled = true;
return;
}
else
{
hour2_image.enabled = false;
colon1_image.enabled = false;
}
if (minute1 > 0)
{
minute1_image.enabled = true;
minute2_image.enabled = true;
colon2_image.enabled = true;
second1_image.enabled = true;
second2_image.enabled = true;
return;
}
else
{
minute1_image.enabled = false;
}
if (minute2 > 0)
{
minute2_image.enabled = true;
colon2_image.enabled = true;
second1_image.enabled = true;
second2_image.enabled = true;
return;
}
else
{
minute2_image.enabled = false;
colon2_image.enabled = false;
}
if (second1 > 0)
{
second1_image.enabled = true;
second2_image.enabled = true;
}
else
{
second1_image.enabled = false;
second2_image.enabled = true;
}
}
void SetDisplay(bool flag)
{
hour1_image.enabled = flag;
hour2_image.enabled = flag;
colon1_image.enabled = flag;
minute1_image.enabled = flag;
minute2_image.enabled = flag;
colon2_image.enabled = flag;
second1_image.enabled = flag;
second2_image.enabled = flag;
}
}
![](https://assets.st-note.com/img/1702621696242-12FUz7kNCF.png)
ボタンの作成
並走タイマーのサイズは他のパネルと同じく、960 x 270。ボタンのサイズはそれより一回り小さい 930 x 250
NDI で送らないように、Runner01 Object の下でなく、Background Canvas の下に作成する
他のマウスボタンと同様に、強調色を RGB = (200, 255, 200) (#C8F5C8)に
クリック時()の内容に Runner01Main.Onclick を設定する
![](https://assets.st-note.com/img/1702621495614-dKTcYphzNM.png)
入力欄の作成
サイズはデフォルトの 160 x 30、いい感じの位置に配置しておく
On ENdEdit(String)の内容に Runner01Main.EndEdit を設定する
![](https://assets.st-note.com/img/1702622101336-yw3GzhZ2QA.png)
正しく動くことが確認されたら OK
おつかれさまでした
さらに改良していきます。次は動画&数字フォント画像を外から読めるようにし、起動するたびに読むことで柔軟な運用ができるようにします