時計盤を作成することがあったので実装をこちらにメモしておきます
特殊な実装はしていないのでスクリプトを読めばだいたい理解できると思います
スクリプト
using System; using UnityEngine; using UnityEngine.UI; public class UIClock : MonoBehaviour { [SerializeField] private Transform _imageHourHand; [SerializeField] private Transform _imageMinuteHand; [SerializeField] private Transform _imageSecondHand; private int _hour; private int _minute; private int _second; private float _millisecond; private bool _valid; /// <summary> /// 現在の時間を取得 /// </summary> public int Hour => _hour; public int Minute => _minute; public int Second => _second; #if UNITY_EDITOR private void Reset() { if (_imageHourHand == null) _imageHourHand = CreateRectTransform("Hour", 6, 0.5f); if (_imageMinuteHand == null) _imageMinuteHand = CreateRectTransform("Minute", 4, 0.9f); if (_imageSecondHand == null) _imageSecondHand = CreateRectTransform("Second", 2); } /// <summary> /// Temp の針を作成 /// </summary> private RectTransform CreateRectTransform(string name, float width, float heightRate = 1f) { var rootRect = transform as RectTransform; var gameObject = new GameObject(name, typeof(RectTransform)); gameObject.transform.SetParent(transform); gameObject.transform.localPosition = Vector3.zero; gameObject.transform.localEulerAngles = Vector3.zero; gameObject.transform.localScale = Vector3.one; var image = gameObject.AddComponent<Image>(); image.color = Color.black; var rectTransform = gameObject.GetComponent<RectTransform>(); rectTransform.pivot = new Vector2(0.5f, 0f); rectTransform.sizeDelta = new Vector2(width, rootRect.rect.height / 2f * heightRate); return rectTransform; } #endif /// <summary> /// 起動時に現在の時間を反映 /// </summary> private void Awake() { UpdateTime(DateTime.Now); _valid = true; } /// <summary> /// 一時的に停止 /// </summary> public void Enable(bool enable) { _valid = enable; } /// <summary> /// 時間を更新 /// </summary> public void UpdateTime(DateTime dateTime) { UpdateTime(dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond / 1000f); } public void UpdateTime(int hour, int minute, int second, float millisecond = 0f) { _hour = hour; _minute = minute; _second = second; _millisecond = millisecond; SetAngles(); } /// <summary> /// 現在の値を角度に反映 /// 時計は時計回りに動いてるので角度を逆にする必要があります /// </summary> private void SetAngles() { var localEulerAngles = _imageSecondHand.localEulerAngles; localEulerAngles.z = 360 - _second * (360 / 60); _imageSecondHand.localEulerAngles = localEulerAngles; var t = Mathf.InverseLerp(0, 60, _second); localEulerAngles = _imageMinuteHand.localEulerAngles; localEulerAngles.z = 360 - (_minute + t) * (360 / 60); _imageMinuteHand.localEulerAngles = localEulerAngles; t = Mathf.InverseLerp(0, 60, _minute); localEulerAngles = _imageHourHand.localEulerAngles; localEulerAngles.z = 360 - (_hour + t) * (360 / 12); _imageHourHand.localEulerAngles = localEulerAngles; } private void Update() { if (!_valid) return; _millisecond += Time.deltaTime; if (_millisecond < 1f) return; // 時間の加算 _millisecond -= 1f; _second++; if (_second >= 60) { _second = 0; _minute++; if (_minute >= 60) { _minute = 0; _hour = _hour + 1 % 24; } } SetAngles(); } }