C# Tutorialを触ってみる1.1 - Clock -


Unity Tutorialとは

Unityについて調べていたらとても素晴らしいTutorialを見つけました。

Unityの勉強に丁度いいと思ったのでやってみます。
なお筆者の英語力は戦闘力5にも満たないので、解釈を間違っていたらすいません
と先に保険をかけておきます。

Clock

まずはTutorial 1-1 Clockから始めます。
完成形は以下の図です。
(わかりにくいですが、一応時計です)

今回行う要素としてはざっと以下の通り(最初のチュートリアルなのでかなり基本的なことから)
* オブジェクトの作成
* スクリプトの作成
* オブジェクトの回転
* 時間の取得

ではTutorialに沿って順番にやってみます。

1.Creating the clock

まずは時計の針の作成ですね。
針のオブジェクトにはCubeを使用します。
まず、Hierarchyから時計の針を格納する空のオブジェクト(Clock)と
それぞれの針に対応する空のオブジェクト(Hours, Minutes, Seconds)を作成し
その配下に針(Cube)を作成します。

2017-03-03_155718.png

Cubeのサイズはそれぞれ
* Hours : position(0, 1, 0) scale(0.5, 2. 0.5)
* Minutes : position(0, 1.5, 0) scale(0.25, 3, 0.25)
* Seconds : position(0. 2. 0) scale(0.1, 4. 0.1)

と設定します。
なぜCubeをそれぞれオブジェクトの配下で作成しているのでしょうか。
見やすくする為という理由もあるかもしれませんが、おそらく今回は針の回転処理を楽にするためだと思います。
時計の針は針の根本から回転しますが、そのまま針(Cube)を回転させるとオブジェクトの中央で回転してしまいます。
ですのでオブジェクト(Hours,Minutes,Seconds)の中心に針(Cube)の回転軸が来るように配置し、オブジェクトを回転させれば針が根本から回転するという仕組みですね。
これについては回転の時にも少し説明します。

2.Animating the clock

次は針を回転させるスクリプトを作成します。
まずClockAnimatorという名前のC#スクリプトを作成し、Clockにアタッチします。

次に作成したスクリプトにそれぞれの針の状態を格納する変数を宣言します。

using UnityEngine;

public class ClockAnimator : MonoBehaviour {

    public Transform hours, minutes, seconds;

}

publicで変数を宣言することで、Inspectorから値を観測することが出来ます。
そこにそれぞれ作成したオブジェクトをドラッグしてアタッチします。

次に単位時間あたりの回転角を定義します。
回転の角度は1時間が360/12度、分・秒が360/60度です。

private const float
    hoursToDegrees = 360f / 12f,
    minutesToDegrees = 360f / 60f,
    secondsToDegrees = 360f / 60f;

最後に現在の時刻を取得し、回転を行います。
時間を取得するにはDateTimeというクラスを使用しますが、使用するには Systemをインクルードする必要があります。

using System

private void Update () {
    DateTime time = DateTime.Now;
    hours.localRotation =
        Quaternion.Euler(0f, 0f, time.Hour * -hoursToDegrees);
    minutes.localRotation =
        Quaternion.Euler(0f, 0f, time.Minute * -minutesToDegrees);
    seconds.localRotation =
        Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);
}

Update()はフレーム毎に呼ばれる関数です。

    DateTime time = DateTime.Now;

で時間を取得し

Transform.localRotation

を使用して回転します。
Quaternionについては長くなるので詳しい説明は割愛しますが(自分も理解しきれていない)

Quaternion.Euler(x, y, z)

は、(x,y,z)のそれぞれの軸に対して入力された角度回転します。
この時回転する中心点は、1でも触れましたがオブジェクトの中心です。
2.で作成したTransformをCubeにそれぞれアタッチして回転させると以下のような回転をします(短針だけ離れていますが気にしないでください)。

図の通りオブジェクトの中心を軸に回転しています。
また、ワールド座標で回転させた場合でも、回転方向はワールド基準ですが、回転の軸はオブジェクトの中心になるようです。

ちなみに回転軸をエディターで見るには、表示をPivotにする必要があるそうです(左上にあるやつです)。

センターだとこうなります。

Tutorialのように表示するにはPivotに設定してください。

あとはこのまま実行すれば現在の時刻が表示されると思います。

3.improvinig the clock

今のままだと、針はそれぞれ時、分、秒単位でしか動きません。
この項目では滑らか(アナログ)な動きを選択できるようにします。

DataTimeでは整数単位でしか値を取得出来ないので、TimeSpanを使用します。

public bool analog;
private void Update () {
    if (analog) {
        TimeSpan timespan = DateTime.Now.TimeOfDay;
        hours.localRotation = Quaternion.Euler(
            0f, 0f, (float)timespan.TotalHours * -hoursToDegrees);
        minutes.localRotation = Quaternion.Euler(
            0f, 0f, (float)timespan.TotalMinutes * -minutesToDegrees);
        seconds.localRotation = Quaternion.Euler(
            0f, 0f, (float)timespan.TotalSeconds * -secondsToDegrees);
    }
    else {
        DateTime time = DateTime.Now;
        hours.localRotation =
            Quaternion.Euler(0f, 0f, time.Hour * -hoursToDegrees);
        minutes.localRotation =
            Quaternion.Euler(0f, 0f, time.Minute * -minutesToDegrees);
        seconds.localRotation =
            Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);
    }
}

timeSpanはdoubleで値が帰ってくるのでfloatでキャストしています。
また、アナログな動きを選択できるようするためフラグを宣言し、場合分けしています。

これで時計の完成です。
この動きに関しては画像では伝えることが出来ないですが、一度作成してみればすぐにわかると思います。

針だけだと何かわからないので、透明の円で囲んでみました。
あとは数字があれば時計っぽくなるかも。