プレイヤーの名前とクリアタイムを表示できるようにする【コピペで使えるサンプルコード付き】

:::note info
本記事は、[HeliScriptでリッチなアスレチックワールドを作ろう！【コピペで使えるサンプルコード付き】](https://qiita.com/IwahanaFuku/private/63e6bbca2bc1f13ed57e)の記事の一部です

VR法人HIKKYのorganization下のQiita/Zenn両方に投稿しております。
:::

# はじめに
アスレチックのリザルト表示として、ゲームをクリアするまでの経過時間と、プレイヤーの名前を表示できるようにします。
HEO Text Planeコンポーネント使用することで、テキストをスクリプトから動的に変更することが出来るようになります。
経過時間は、わかりやすいように、**mm:ss.ms**といった表示が行えるようにします。

# プレイヤーの名前を表示する
![2024-05-08 23-01-27_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/f24ae7e4-3ef9-d39e-0cdc-b76ba1a67e32.gif)

**Unity設定画面**
**プレイヤーの名前を表示するボタン**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/b3cab17f-e35f-8d67-4d35-bf40a6d5eed8.png)

**プレイヤーの名前を表示するHEO Text Plane**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/ec09919a-ad69-5d94-49ed-5907105c0431.png)

**コード全文**
```C#:ShowPlayerName.hs
component ShowPlayerName
{ 
    public void ShowText()
    {
        Item playerNameText = hsItemGet("PlayerNameText");
        string playerName = hsPlayerGet().GetName();
        playerNameText.WriteTextPlane(playerName);
    }
}
```
## コード解説
HEO TextPlaneコンポーネントで配置したテキストをHeliScriptから制御するには、[WriteTextPlane(string text)](https://vrhikky.github.io/VketCloudSDK_Documents/5.4/ja/hs/hs_class_item.html#writetextplanestring)関数でテキストの内容を変更することが出来ます。

この関数では、PlayerNameTextというアイテムと、プレイヤーの名前を取得して、`WriteTextPlane()`関数で、プレイヤーの名前を書き込む関数を作成しています。

# カウントアップタイマーを表示する
![2024-05-08 23-01-27_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/e0d2c0e9-dd85-5c6e-fe56-08f221671aa0.gif)

**Unity設定画面**
**カウントアップをスタートするボタン**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/17fc31f7-6dcb-ac1a-9827-eac6073b2083.png)

**カウントアップをストップするボタン**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/640b5e8f-7897-84bc-3585-db78de9a2432.png)

**カウントアップを表示するHEO Text Plane**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/e00a9bc5-1d4a-459c-539d-572f0cc9b9b8.png)

**コード全文**
```C#:CountUpTimer.hs
component CountUpTimer
{
    int triggerStartSystemTime;
    bool m_isCount;
    Item countUpTimerText;
    
    public CountUpTimer()
    {
        countUpTimerText = hsItemGet("CountUpTimerText");
    }

    public void Update()
    {
        Count();
    }

    void Count()
    {
        if(m_isCount)
        {
            int startDurationTime = hsSystemGetTime() - triggerStartSystemTime;
            countUpTimerText.WriteTextPlane(FormatMilliseconds(startDurationTime));
        }
    }

    public void StartCountUpTimer()
    {
        m_isCount = true;
        triggerStartSystemTime = hsSystemGetTime();
    }

    public void StopCountUpTimer()
    {
        m_isCount = false;
    }

    string FormatMilliseconds(int milliseconds)
    {
        string result;

        // ミリ秒から分を計算
        int minutes = milliseconds / 60000;
        // 残りのミリ秒から秒を計算
        int seconds = (milliseconds % 60000) / 1000;
        // 残りのミリ秒
        int millis = (milliseconds % 1000) / 10;

        //mm:ss.ms の形式でフォーマット
        result = ZeroPadding(minutes, 2) + ":" + ZeroPadding(seconds, 2) + "." + ZeroPadding(millis, 2);

        return result;
    }

    //指定した文字数分0で埋める関数
    string ZeroPadding(int num, int length)
    {
        string result = num.ToString();

        //numとして渡した0で埋めたい数字と、0埋めする長さを比較して、
        //0埋めする長さの方が大きければその分0を文字列に追加する
        if(result.Length() < length)
        {
            string seriesOfZeros = "";

            for(int i = 0; i < length - result.Length(); i++)
            {
                seriesOfZeros += "0";
            }

            result = seriesOfZeros + result;
        }

        return result;
    }
}
```

## コード解説
### カウントアップをスタートしてからの経過時間をミリ秒で取得する
```C#
    public void Update()
    {
        Count();
    }

    void Count()
    {
        if(m_isCount)
        {
            int startDurationTime = hsSystemGetTime() - triggerStartSystemTime;
            countUpTimerText.WriteTextPlane(FormatMilliseconds(startDurationTime));
        }
    }

    public void StartCountUpTimer()
    {
        m_isCount = true;
        triggerStartSystemTime = hsSystemGetTime();
    }

    public void StopCountUpTimer()
    {
        m_isCount = false;
    }
```
時間の経過を取得するために、[hsSystemGetTime()](https://vrhikky.github.io/VketCloudSDK_Documents/12.3/hs/hs_system_function.html#hssystemgettime)という、VketCloudが起動してからの経過時間をミリ秒単位で返すシステム関数を使用します。

計測を開始した瞬間の経過時間を、VketCloudが起動してからの経過時間から引くことで、カウントアップタイマーが起動した瞬間を0として、経過時間がミリ秒で取得できるようになります。

### 0埋めするための関数を作成する
```C#
    //指定した文字数分0で埋める関数
    string ZeroPadding(int num, int length)
    {
        string result = num.ToString();

        //numとして渡した0で埋めたい数字と、0埋めする長さを比較して、
        //0埋めする長さの方が大きければその分0を文字列に追加する
        if(result.Length() < length)
        {
            string seriesOfZeros = "";

            for(int i = 0; i < length - result.Length(); i++)
            {
                seriesOfZeros += "0";
            }

            result = seriesOfZeros + result;
        }

        return result;
    }
```
 `string ZeroPadding(int num, int length)`は、int型のナンバーと、0埋めした後の数字の長さを渡すことでゼロ埋めされた数字をstringで返すための関数です。
文字列の長さは[Length()](https://vrhikky.github.io/VketCloudSDK_Documents/12.3/hs/hs_string.html#length)で取得することが出来るため、ゼロ埋めした後の長さと、Lengthを引いて実際に追加しないといけない0の数を求めることが出来ます。
追加しないといけない0の文字列を作って、文字列化したnumを足し合わせることで、0埋めされた数字の文字列を取得することが出来るようになります。

:::note info
VketCloudSDK 12.3時点でのマニュアルには記載されていませんが、C言語の[printfの0埋めと桁揃え【C言語】](https://qiita.com/39_isao/items/54a82eca44ff1eab6b4d)の表記方法も使用可能です。
:::


### ミリ秒の経過時間をmm:ss.msで表示できるようにする
```C#
    string FormatMilliseconds(int milliseconds)
    {
        string result;

        // ミリ秒から分を計算
        int minutes = milliseconds / 60000;
        // 残りのミリ秒から秒を計算
        int seconds = (milliseconds % 60000) / 1000;
        // 残りのミリ秒
        int millis = (milliseconds % 1000) / 10;

        //mm:ss.ms の形式でフォーマット
        result = ZeroPadding(minutes, 2) + ":" + ZeroPadding(seconds, 2) + "." + ZeroPadding(millis, 2);

        return result;
    }
```
`startDurationTime`から、分、秒、10ミリ秒の値を取得します。

1分は 60000 ミリ秒に相当するため、ミリ秒を 60000で割ることによって、総分数が求められます。
1秒は、ミリ秒を 1000で割ることによって、総秒数が求められます。ただ、そのまま1000で割ってしまうと分の位に含まれるはずの経過時間も含まれてしまうため、 60000 で割った余りを 1000 で割ることで、必要な経過時間は分の位に繰り上がった秒の位が求められます。
同じ要領で、10ミリ秒単位の数値を取得するために、ミリ秒数を 1000 で割った余りからさらに10で割ります。

これで分、秒、10ミリ秒の値が取得できたため、`ZeroPadding(int num, int length)`関数を使用して、mm:ss.ms形式にフォーマットします。

これでカウントアップタイマーの完成です！

 **前 :** [HeliScriptでアイテムを揺らす【コピペで使えるサンプルコード付き】](https://qiita.com/IwahanaFuku/private/607d73db767362c0162f) 
 **次 :** [今まで作ったcomponentを使ってワールドを完成させる](https://qiita.com/IwahanaFuku/private/3aff716f20ec998144ad)