分針を上下に動かす|Unityで針が縦に動く時計を作る

Photo by Monty Allen on Unsplash Unity
Photo by Monty Allen on Unsplash

こんにちは。コンスキです。

以前から、Unityで針が縦に動く時計を作っています。

秒針を上下に動かす部分は以前やったので、今回は分針を上下に動かすスクリプトを書きます。

基本的には秒針と同じやり方でできるのですが、もう一度説明させてもらうので、秒針での説明がわかりづらかった方は参考にしてください。

ちなみに、秒針を上下に動かすスクリプトは次の記事で紹介しています。

分棒を上下に動かす

分針と分棒の区別

ここからは、回転する分針のことを単に「分針」、上下に動く分針のことを「分棒」と呼ぶことで2つを区別しています。

分針のスクリプト

まずは、次の分針を動かすスクリプトを見てみましょう。

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

public class MinuteHandManager : MonoBehaviour
{
  public Vector3 minuteHandAngle;
  // Start is called before the first frame update
  void Start()
  {

  }

  // Update is called once per frame
  void Update()
  {
    int m = DateTime.Now.Minute;
    minuteHandAngle = new Vector3(0, 0, -360 / 60.0f * m);
    GetComponent<Transform>().localEulerAngles = minuteHandAngle;
  }
}

分棒の位置を決めるために、分針の角度を使います。

8行目がその宣言をしている部分です。

public Vector3 minuteHandAngle;

そこで、分針のスクリプトにおいて、分針の角度の変数を宣言しておきます。

ここで重要なのが、「public」をつけて宣言していることです。

他のスクリプトの変数を使うには、あらかじめその変数を「public」をつけて宣言している必要があります。

次に、19行目を見てください。

minuteHandAngle = new Vector3(0, 0, -360 / 60.0f * m);

この行では、「public」をつけて宣言した変数に分針の角度を代入しています。

ちなみに分針の角度は、DateTime.Now.Minuteプロパティで取得した現在時刻を使って計算しています。

ここでは詳しく触れませんがその計算については、次の記事で書いています。

分棒のスクリプト

先ほど「public」をつけて分針の角度の変数を宣言しました。

そして、そこに分針の角度を入れました。

これで分針のスクリプト側での準備はできました。

分棒のスクリプト側でも、角度の変数を使う準備が少し必要になります。

次の分棒を動かすスクリプトを見てください。

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

public class MinuteBarManager : MonoBehaviour
{    
    GameObject minuteHand;
    MinuteHandManager script;
    
    // Start is called before the first frame update
    void Start()
    {
        minuteHand = GameObject.Find ("Minute Hand");
        script = minuteHand.GetComponent<MinuteHandManager>();        
    }

    // Update is called once per frame
    void Update()
    {
        var minuteHandAngle = script.minuteHandAngle;
        double theta = (double)(minuteHandAngle.z + 90.0);
        double radian = Math.PI * theta / 180.0;
        float y = (float)(384.0 * Math.Sin(radian));
        GetComponent<Transform>().position = new Vector3(356.0f, y, 0);           
    }
}

まず、4行目です。

using System;

後でMathクラスのPIというフィールド(値)やSin(Double)というメソッドを使うためにこのように書いています。

次は8行面と9行目です。

GameObject minuteHand;
MinuteHandManager script;

この2つの行では、ゲームオブジェクト(スプライト)の情報やそれに追加したスクリプトの情報を入れるための変数用意しています。

次は14行目と15行目です。

minuteHand = GameObject.Find ("Minute Hand");
script = minuteHand.GetComponent<MinuteHandManager>();    

8行目と9行目で用意した変数に、ゲームオブジェクトとそれに追加したスクリプトの情報をそれぞれ入れています。

これで、分針の角度の変数を使う準備は全てできました。

次に21行目を見てください。

var minuteHandAngle = script.minuteHandAngle;

この行でようやく分針の角度の変数を取得しています。

次は、22行目から25行目についてです。

double theta = (double)(minuteHandAngle.z + 90.0);
double radian = Math.PI * theta / 180.0;
float y = (float)(384.0 * Math.Sin(radian));
GetComponent<Transform>().position = new Vector3(356.0f, y, 0); 

ここからは、分針の角度から分棒の位置を計算する部分に入っています。

まず、22行目で角度の変換をしています。

角度の変換とは、「y=rsinθ」の式で使える角度に変換するという意味です。

実は、この変換をせずに計算を進めてしまうと、分針の先端のy座標と分棒のy座標がずれてしまいます。

変換前の角度は下の図のように、時計の12時の方向から分針との間の角度を表しています。

一方で、「y=rsinθ」計算で使いたい角度θは、図の右側の円で示しているように、x軸のプラス側と分針との角度です。

変換しないと、この違いが原因で、分針の先端のy座標と分棒のy座標に違いが出てきてしまいます。

23行目では、角度をラジアンに直しています。

ラジアンにする前は0から-360の数字で角度を表していました。

ラジアンにすることで、0から-2πで表すことができます。

ラジアンにする理由は、「y=rsinθ」の計算で使うθがラジアンを前提にしているからです。

これもまた、ラジアンにしないと分針の先端のy座標と分棒のy座標に違いが出てきてしまいます。

そして、24行目で「y=rsinθ」の計算をやっています。

ここでは、時計の中心から分針の先端までの長さが「384」であったため、「r=384.0」として計算をしています。

最後に、25行目では「GetComponent().position」に先ほど計算した分棒のy座標を入れています。

完成形

ここまでで、秒棒に加えて分棒も上下に動くようになりました。

コメント

タイトルとURLをコピーしました