簡単に軽い時計を作ってみた

#はじめに
こちらの記事は[VCI Advent Calendar 2020](https://qiita.com/advent-calendar/2020/vci)の第２０日目の記事です。

202/12/22：スクリプト修正、アイテムを出してすぐに同期するように変更

#前回の記事の反省

前回は内容がマニアックすぎだと反省したので、今回は簡単に時計を作ってみたいと思います。
全くの初心者の方にはきついのですが、Wikiなどを参考にすれば出来ると思います。
説明しながらの作成講座はこちらで行う予定なので分からないときは勉強会をお待ちください。
[「VCI勉強会－なんもわからんから始めるVCI－」](https://com.nicovideo.jp/community/co3873429)

#時計の3Dモデルを作成する
バーチャルキャストのWikiでも時計を作っていますが、折角なので少し説明します。
UnityのCubeとTextMeshProを使用して時計のモデルを作成します。

手順を書きます。
１．Unityのプロジェクトを立ち上げる
２．UniVCIを読み込む
３．TextMeshProを使えるようにする
４．VCIのオブジェクトを作成する
５．EmptyObjectをSubItemに設定する
６．５．の下にBoxを置く
７．６．のBoxをいい感じの大きさにする
８．Boxのいい場所にTexMeshProを貼り付けて00:00を書き込む
９．00:00が表示が良い大きさになるように調整する
１０．BoxにMaterialを設定して好きな色にする

これで時計のVCIのモデルが完成です！
実際にやると10分程度でできると思いますが、分からない方には何のことか分からないと思います。

全部を解説すると今回だけでは書ききれないので、勉強会の方をお待ちください。

設定が終わった後のHierarchyとInspectorの画像を貼り付けますので参考にしてください。

VCIアイテム（TOKEIの設定 1/3）
![01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/d96eb1d3-325f-7194-f4f0-17ec0dc207bd.jpeg)

VCIアイテム（TOKEIの設定 2/3）
![02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/68c5631c-5015-cf8b-ed47-96b28266a6d4.jpeg)

VCIアイテム（TOKEIの設定 3/3）
![03.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/1609373c-458b-6aa9-e38d-4320dabeb6c4.jpeg)

SubItem（TOKEI01の設定）
![04.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/62dc7f82-83b5-7736-7516-b08b98cdfeab.jpeg)

TOKEI01の子アイテムの外形設定
![05.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/ac209f73-0399-2588-9e01-5c5af4a79c31.jpeg)

TOKEI01の子アイテムテキスト設定
![06.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/e45e26d3-6031-b71c-8608-52cb8a73014a.jpeg)

#適当に作った時計のモデル
今回はUnityのCubeを小さくして使用しましたが、好きな時計のモデルをBlenderなどで作成してあげると好きな形の時計になります。

今回作ったのはこんな感じです。
![07.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/9e305308-579d-9163-edc8-0f952f421edf.jpeg)

ここまでやると00:00の白色が気になりますが、こちらはLuaで変更できるので保留です。
Boxの色もLua変更できますが、今回はやりませんのでMaterialの設定で好きな色に変更してください。

#Luaを考える
やっとメインです。
時計は今の時間が表示されれば問題ありませんから、定期的に時間を読んでTextMeshProで表示すれば良さそうです。

Wikiのサンプルに有る時計でも動きますし問題は無いのですが、折角作るので少し軽くして、少し機能を付けて遊びましょう。

#一人が処理をするように考える
時計は1人が書き換えてみんなが見れば、処理を行う方が１人ですみますね。
1人で処理を行うと、他の方の環境で余計な処理が動かなくなるのでおすすめです。
ただ、時差のある方が枠に入ると、日本時間が表示されます。

でも、今回は気にしない。

処理のイベントにはupdateを使用して、表示にはvci.assets._ALL_SetTextを使うと解決です。

#サンプルのLuaです
updateを使って、いろいろと処理を軽くする方法を入れて、さらに以前にアドカレで書いた角度補正も追加して見ました。
あと00分に音も出ます。

```Lua:Tokei.lua
-- 簡単に時計を作ってみた
-- 2021/02/09 いろいろ修正、コメント追加

-- 変数の宣言
local SubItemName01 = "Tokei"
local Item01 = vci.assets.GetSubItem(SubItemName01)
-- 000000:黒、FFFFFF：白、FF0000：赤、00FF00：緑、0000FF：青、FFFF00:黄、
-- FF00FF：マゼンタ、00FFFF：アクア
local TimeColor = "<#00FF00>" -- 時計の文字色
local Counter=30 -- updateを実行する間隔30fpsに1回に設定
--local Time
local TimeB = ""
local Volume = 0.2 --音の大きさ、0無音、1最大
local Flag = false
-- 変数の宣言ここまで
--------------------
-- 関数とかを並べて書いていく
function update() -- VCIを出した人だけが実行する
    if Counter > 30 then -- 30フレームに一回実行、最大1秒に3回
        Counter = 0 --カウンターのリセット
        -- 時分の表示
        local Time = os.date("%H:%M") --今の時間の取り込み
        local ZeroCheck = os.date("%M") --分だけ別に取り込み			
        if Time ~= TimeB then --前回表示した時間と今の時間が違っていれば処理1分経過
            -- 時間の表示 全員に同じものを表示する
            vci.assets._ALL_SetText("Text", TimeColor..tostring(Time))
            if ZeroCheck == "00" then --00分ならベルを鳴らす
                vci.assets.audio._ALL_Play("Bell",Volume,false)
            end
            TimeB=Time --書き換えた時間を前の時間に保存
        end
    end
    Counter = Counter +1 -- カウンターを1個進める
end

--Grab時の角度補正ルーチン 使いまわし可能 ここは所有権の有る人だけで動く
--角度補正の計算をするところ
function Modification(X)
	local Angle = 15 --角度補正値 15度
    local XX = math.floor(X/Angle+0.5)
    XX = XX*Angle
    return XX
end

--握ったことをフラグに残す
function onGrab(target)
    if target == SubItemName01 then
        Flag = true
    end
end

-- 離した時にtargetがSubItemName01なら角度補正
function onUngrab(target)
    if Flag == false or target ~= SubItemName01 then
        return
    end
    local rotate = Item01.GetRotation()   --アイテムの角度 eular
    local X = Modification(rotate.eulerAngles.x)
    local Y = Modification(rotate.eulerAngles.y)
    local Z = Modification(rotate.eulerAngles.z)
    local Kakudo = Quaternion.Euler(X, Y, Z) --アイテムの角度
    Item01.SetRotation(Kakudo) -- Itemの角度を変更すると全員の角度が反映
	Flag = false
end
--Grab時の角度補正ルーチン終了

-- 関数とか終了
----------------------------
-- 初期化の処理をここから下に書く
-- アイテムを出した時、部屋に入った時に一度時計の表示に現在時刻を表示する
TimeB = os.date("%H:%M") --今の時間の取り込み
vci.assets.SetText("Text", TimeColor..tostring(TimeB))
```

#なにをやっているか？
Updateを使用するとVキャスの毎フレームごとに処理が入ります。
つまり最大1/90秒ごとに時計の書き換えを行います。

今回の時計は1分ごとに更新すればいいのですから、1/90も書き換えなくて大丈夫ですね。
間引きましょう。

カウンターを入れて30fpsに1回にして、ちょっとサボりました。
あと前に表示した時間を入れて、時間が同じときは再表示しないようにしてみました。

#まだ軽くできるんじゃないの？
あっ、すみません。
もう一個、コルーチンってやつが有りまして、えっ、時間切れ？
その話はまた機会が有りましたら・・・。

#軽い以外の機能について
今回の時計は好きな色で作れるようにして、軽くて、音が出る機能を追加します。

・文字の色の変え方の説明
・00分になったら、時計から音が出る

#文字色を変更する
```Lua:色変更するところ.lua
local TimeColoe = "<#FFFF00>"
```
Tokei.luaの上の行を書き換えます。
<#FFFF00>は黄色、<#FFFFFF>は白、<#000000>は黒という感じです。
カラーコードはWebで調べて好きな色を入れてみてください。
そしてオリジナル時計をVキャスのお部屋に飾って自慢してください。

#音を追加する
音を入れる場合、次の2個は絶対に守ってください。
・音を入れる場合は権利関係に注意して著作権フリーの素材、または自分で録音した音を使ってください。
・ボリュームは0.1くらいから少しずつ上げて迷惑にならない程度の音量に調整してください。

```Lua:色変更するところ.lua
local Volume = 0.3
```
こちらの0.3を1.0までの間で大きくすと音が大きくなり、0に近づくと小さくなります。
まずUnityのItem（説明だとTOKEI）にAdd ComponentでAudio Sourceを追加して、好きな音声データをAudioClipにセットします。

#おわりに
今回作成した時計のサンプルをTSOにアップしましたのでご参考に。
[デジタル時計](https://seed.online/products/0c1048df1199ff691892188739c80c9e838eb1ec30560cb75b13de86231abe51)
![2020122013082459.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/ab4b75b0-a491-d0a1-2b34-23b89f9ad001.jpeg)

今回は時計を簡単に作るのが目的でしたが、VCIを作ったことの無い方には少し難しいと思います。
この辺りはニコ生の枠の中で説明していければいいなと思っていますので、興味のある方は遊びにきてください。

また、こちらに記載しているLuaプログラムはご自由にコピーして書き換えて使用してください。
ただし書き換えによって生じた問題については自己責任でお願いします。

[TSO にゃふ屋](https://seed.online/users/106600#products)

それでは、まったね～。:blush: